/***************************************************************************
 *   Copyright (C) 2010 by joker                                           *
 *   joker@pleiades.pet.cyric.tohoku.ac.jp                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "shmio.h"
#include "aboutcls.h"
#include "rp3dReconCls.h"
#include "pix.h"
#include "rdmancls.h"
#include "cleardlgcls.h"
#include "setman.h"
#include "ori.h"
#include "config.h"

#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/sysctl.h>

#include <qstringlist.h>
#include <qlistbox.h>
#include <kfileitem.h>
#include <qpushbutton.h>
#include <qprocess.h>
#include <qlineedit.h>
#include <qtextedit.h>
#include <qtimer.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qpopupmenu.h>
#include <qspinbox.h>
#include <qevent.h>
#include <qdatetime.h>
#include <qtabwidget.h>
#include <qcombobox.h>
#include <qfile.h>
#include <qlabel.h>
#include <qprogressbar.h>
#include <qevent.h>
#include <qtooltip.h>
#include <qwidgetstack.h>
#include <qmotifstyle.h>
#include <qdatetimeedit.h>

#include <kfiledialog.h>
#include <kurl.h>
#include <klistview.h>
#include <kled.h>
#include <kconfig.h>
// #include <kconfigbase.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <knuminput.h>
#include <kcombobox.h>
#include <kcompletion.h>
#include <kglobalsettings.h>

rp3dReconCls::~rp3dReconCls()
{
}

void rp3dReconCls::closeEvent ( QCloseEvent *e )
{
	if ( confirmExitBox->isChecked() )
	{
		if ( KMessageBox::No==KMessageBox::questionYesNo (
		            this,
		            tr ( "Are You Sure You Want to Exit?" ),
		            tr ( "Question" ),tr ( "Yes" ),tr ( "No" ) ) )
			return;
	}
	saveConfig ( HOME+CONFIG );
	if ( shmid>0 ) close_shm();
	exit ( 0 );
}

bool rp3dReconCls::str2bool ( QString s )
{
	if ( s.lower() =="true"||s.lower() =="t"||s.lower() =="y"||s.lower() =="yes" || s.lower() =="1"||s.lower() =="on" )
	{
		return true;
	}
	else
	{
		return false;
	}
}

void rp3dReconCls::loadReconConfig ( KConfig *c, QString n )
{
	QString s;
	bool on;

	KConfigGroup reconGroup ( c,n );

	s=reconGroup.readEntry ( "Detector separation","150" );
	detectorSeparationBox->setValue ( s.toInt() );
	s=reconGroup.readEntry ( "Number of iteration","4" );
	iteBox->setValue ( s.toInt() );
	sliceThicknessBox->setValue ( reconGroup.readDoubleNumEntry ( "Slice thickness in mm",1.0 ) );
	sThBox->setValue ( reconGroup.readDoubleNumEntry ( "Lower sensitivity cut in %",0.0 ) );
	maxcdBox->setValue ( reconGroup.readNumEntry ( "Maximum crystal difference",-1 ) );
	AAFBox->setValue ( reconGroup.readDoubleNumEntry ( "Antialiasing parameter",0.0 ) );

	int id;
	int k;
	switch ( k=reconGroup.readNumEntry ( "Multiray sampling",1 ) )
	{
		case 1:
			id=0;
			break;
		case 4:
			id=1;
			break;
		case 9:
			id=2;
			break;
		default:
			id=0;
			printmsg ( "Invalid multiray sampling: "+QString::number ( k ),"red" );
			break;
	}
	mrsBox->setCurrentItem ( id );
	//
	fovRadBox->setValue ( reconGroup.readDoubleNumEntry ( "FOV radius in mm",70 ) );
	setComboItem ( lineIntBox,reconGroup.readNumEntry ( "Line integral sampling",1 ) );
	MRPBox->setValue ( reconGroup.readDoubleNumEntry ( "MRP parameter",0.0 ) );
	maxddBox->setValue ( reconGroup.readNumEntry ( "Maximum detector difference",-1 ) );

	senFileEdit->setText ( reconGroup.readEntry ( "Sensitivity correction data file","" ) );
	uniFileEdit->setText ( reconGroup.readEntry ( "Uniformity correction data file","" ) );
	setComboItem ( ofmtBox,reconGroup.readEntry ( "Output format","dicom" ) );

	if ( RECON.find ( "emily" ) >=0 )
	{
		recon_mode=RM_EMILY;
		THEOPT = reconGroup.readEntry ( "Options for emily","" );
	}
	else if ( RECON.find ( "meliy" ) >=0 )
	{
		recon_mode=RM_MELIY;
		THEOPT = reconGroup.readEntry ( "Options for meliy","" );
	}
	else
	{
		recon_mode=RM_UNKNOWN;
		/*		THEOPT = reconGroup.readEntry ( "Options for reconstrucion","" );
				THEARGS = reconGroup.readEntry("Arguments for reconstruction");*/
	}
	emilyOptBox->setCurrentText ( THEOPT );
	emilyOptBox->addToHistory ( THEOPT );
}

void rp3dReconCls::loadConfig ( QString f )
{
	KConfig *conf = new KConfig ( f );
	if ( conf==NULL ) return;

	bool on;

	printmsg ( "Loading configuration from "+f,"darkgreen",true );

	KConfigGroup generalGroup ( conf, "General" );
	KConfigGroup scriptGroup ( conf,"Scripts" );
	KConfigGroup externalGroup ( conf,"Externals" );
	KConfigGroup miscGroup ( conf,"Miscellaneous" );
	KConfigGroup histGroup ( conf,"History" );

	institutionBox->setText ( generalGroup.readEntry ( "Institution","Cyric, Tohoku Univ." ) );
	DATA = generalGroup.readEntry ( "Data directory",DATA_DEF );
	on=str2bool ( generalGroup.readEntry ( "Use default input directory","false" ) );
	inputDefBox->setChecked ( on );
	on=str2bool ( generalGroup.readEntry ( "Use default output directory","false" ) );
	outputDefBox->setChecked ( on );

	SCRPATH    = scriptGroup.readEntry ( "Script path",SCRPATH_DEF );
	MKHIS      = scriptGroup.readEntry ( "mkhis",MKHIS_DEF );
	MKTHIS     = scriptGroup.readEntry ( "mkthis",MKTHIS_DEF );
	MKEHIS     = scriptGroup.readEntry ( "mkehis",MKEHIS_DEF );
	MKSMAP     = scriptGroup.readEntry ( "mksmap",MKSMAP_DEF );
	MKRMAP     = scriptGroup.readEntry ( "mkrmap",MKRMAP_DEF );
	MKRWNT     = scriptGroup.readEntry ( "mkrawnt",MKRWNT_DEF );
	RECON      = scriptGroup.readEntry ( "recon", RECON_DEF );
	printmsg ( "Reconstruction program: "+RECON,"darkgreen",true );
	loadReconConfig ( conf,"Reconstruction" );

	VIEWER     = scriptGroup.readEntry ( "viewer", VIEWER_DEF );
	PLOTTER    = scriptGroup.readEntry ( "plotter", PLOTTER_DEF );
	PLOTSTER   = scriptGroup.readEntry ( "plotster", PLOTSTER_DEF );
	ANAPLOTTER = scriptGroup.readEntry ( "anaploter", ANAPLOTTER_DEF );
	RUNCOM     = scriptGroup.readEntry ( "runcom",RUNCOM_DEF );

	NOTICE  = externalGroup.readEntry ( "notice",NOTICE_DEF );
	FIND    = externalGroup.readEntry ( "find",FIND_DEF );
	XMEDCON = externalGroup.readEntry ( "Ana viewer",XMEDCON_DEF );
	AMIDE   = externalGroup.readEntry ( "Dicom viewer",AMIDE_DEF );

	webbrowser = externalGroup.readEntry ( "Web browser",BROWSER_DEF );

	on=str2bool ( miscGroup.readEntry ( "Auto set extension","true" ) );
	autoExtBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Allow overwrite","false" ) );
	overwriteBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Ignore file type","false" ) );
	ignoreFiletypeBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Notify when done","false" ) );
	noticeBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Open when done","false" ) );
	automaticViewBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Show file type","true" ) );
	showFileTypeBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Show file size","true" ) );
	showFileSizeBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Show last modified date","true" ) );
	showLMDBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Show last modified time","false" ) );
	showLMTBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Confirm on exit","true" ) );
	confirmExitBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Stay on top","false" ) );
	stayTopBox->setChecked ( on );
	if ( on ) stayTopSlot();

	on=str2bool ( miscGroup.readEntry ( "Auto clear information","false" ) );
	autoCleInfoBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Need confirm on clear information","true" ) );
	confirmCleInfoBox->setChecked ( on );

	on=str2bool ( miscGroup.readEntry ( "Auto remove data","false" ) );
	autoRemoveDataBox->setChecked ( on );
	on=str2bool ( miscGroup.readEntry ( "Need confirm on remove data","true" ) );
	confirmRemoveDataBox->setChecked ( on );

	on=str2bool ( miscGroup.readEntry ( "Remember file location","false" ) );
	rememberFileLocBox->setChecked ( on );

	on=str2bool ( miscGroup.readEntry ( "Auto set output filename","false" ) );
	autoSetFilenameBox->setChecked ( on );

	on=str2bool ( miscGroup.readEntry ( "Log enabled","true" ) );
	logBut->setOn ( on );
	logSlot();

	runComBox->setHistoryItems ( histGroup.readListEntry ( "command history" ) );
	runComBox->completionObject()->setItems ( histGroup.readListEntry ( "command completion" ) );
	switch ( recon_mode )
	{
		case RM_EMILY:
			emilyOptBox->setHistoryItems ( histGroup.readListEntry ( "emilyOpt history" ) );
			emilyOptBox->completionObject()->setItems ( histGroup.readListEntry ( "emilyOpt completion" ) );
			break;
		case RM_MELIY:
			emilyOptBox->setHistoryItems ( histGroup.readListEntry ( "meliyOpt history" ) );
			emilyOptBox->completionObject()->setItems ( histGroup.readListEntry ( "meliyOpt completion" ) );
			break;
		default:
			break;
	}

	operatorBox->setHistoryItems ( histGroup.readListEntry ( "operator history" ) );
	operatorBox->completionObject()->setItems ( histGroup.readListEntry ( "operator completion" ) );

	bodyPartBox->setHistoryItems ( histGroup.readListEntry ( "body part history" ) );
	bodyPartBox->completionObject()->setItems ( histGroup.readListEntry ( "body part completion" ) );

	rpBox->setHistoryItems ( histGroup.readListEntry ( "radiopharm history" ) );
	rpBox->completionObject()->setItems ( histGroup.readListEntry ( "radiopharm completion" ) );

	halflifeBox->setHistoryItems ( histGroup.readListEntry ( "halflife history" ) );
	halflifeBox->completionObject()->setItems ( histGroup.readListEntry ( "halflife completion" ) );

	delete conf;
}
void rp3dReconCls::setComboItem ( QComboBox *c, QString s )
{
	for ( int i=0;i<c->maxCount();i++ )
	{
		if ( c->text ( i ) ==s )
		{
			c->setCurrentItem ( i );
			return;
		}
	}
	c->setMaxCount ( c->maxCount() +1 );
	c->insertItem ( s,-1 );
	c->setCurrentItem ( c->maxCount()-1 );
}
void rp3dReconCls::setComboItem ( QComboBox *c, int a )
{
	for ( int i=0;i<c->maxCount();i++ )
	{
		if ( c->text ( i ) ==QString::number ( a ) )
		{
			c->setCurrentItem ( i );
			return;
		}
	}
	int k=-1;
	for ( int i=0;i<c->maxCount();i++ )
	{
		if ( c->text ( i ).toInt() >a )
		{
			k=i;
			break;
		}
	}
	int i;
	if ( k==-1 )
	{
		i=c->maxCount();
		c->setMaxCount ( c->maxCount() +1 );
	}
	else
	{
		i=k;
	}
	c->insertItem ( QString::number ( a ),k );
	c->setCurrentItem ( i );
}

void rp3dReconCls::saveReconConfig ( KConfig *c, QString n )
{
	KConfigGroup reconGroup ( c, n );

	switch ( recon_mode )
	{
		case RM_EMILY:
			reconGroup.writeEntry ( "Options for emily",emilyOptBox->currentText() );
			break;
		case RM_MELIY:
			reconGroup.writeEntry ( "Options for meliy",emilyOptBox->currentText() );
			break;
		default:
			/*		reconGroup.writeEntry ( "Options for reconstruction",emilyOptBox->currentText() );
					reconGroup.writeEntry("Arguments for reconstruction",THEARGS);*/
			break;
	}

	reconGroup.writeEntry ( "Detector separation",QString::number ( detectorSeparationBox->value() ) );
	reconGroup.writeEntry ( "Number of iteration",QString::number ( iteBox->value() ) );
	reconGroup.writeEntry ( "Slice thickness in mm",QString::number ( sliceThicknessBox->value() ) );
	reconGroup.writeEntry ( "Lower sensitivity cut in %",QString::number ( sThBox->value() ) );
	reconGroup.writeEntry ( "Maximum crystal difference",QString::number ( maxcdBox->value() ) );
	reconGroup.writeEntry ( "Multiray sampling",mrsBox->currentText() );
	reconGroup.writeEntry ( "Antialiasing parameter",AAFBox->value() );
	if ( recon_mode==RM_MELIY )
	{
		reconGroup.writeEntry ( "FOV radius in mm",QString::number ( fovRadBox->value() ) );
		reconGroup.writeEntry ( "Line integral sampling",lineIntBox->currentText() );
		reconGroup.writeEntry ( "MRP parameter",QString::number ( MRPBox->value() ) );
		reconGroup.writeEntry ( "Maximum detector difference",QString::number ( maxddBox->value() ) );
	}
	reconGroup.writeEntry ( "Sensitivity correction data file",senFileEdit->text() );
	reconGroup.writeEntry ( "Uniformity correction data file",uniFileEdit->text() );
	reconGroup.writeEntry ( "Output format",ofmtBox->currentText() );

	reconGroup.sync();

}

void rp3dReconCls::saveConfig ( QString f , int veto )
{
	if ( !fileExists ( f ) )
	{
		if ( !QFile ( f ).open ( IO_WriteOnly ) ) return;
	}
	KConfig *conf = new KConfig ( f );
	if ( conf==NULL ) return;

	KConfigGroup generalGroup ( conf, "General" );
	KConfigGroup scriptGroup ( conf,"Scripts" );
	KConfigGroup externalGroup ( conf,"Externals" );
	KConfigGroup miscGroup ( conf,"Miscellaneous" );
	KConfigGroup histGroup ( conf, "History" );

	if ( ! ( veto&CLE_GEN ) )
	{
		generalGroup.writeEntry ( "Institution",institutionBox->text() );
		generalGroup.writeEntry ( "Data directory",datapathEdit->text() );
		generalGroup.writeEntry ( "Use default input directory",inputDefBox->isChecked() );
		generalGroup.writeEntry ( "Use default output directory",outputDefBox->isChecked() );
	}

	if ( ! ( veto&CLE_REC ) )
	{
		saveReconConfig ( conf,"Reconstruction" );
	}

	if ( ! ( veto&CLE_SCR ) )
	{
		scriptGroup.writeEntry ( "Script path", SCRPATH );
		scriptGroup.writeEntry ( "mkhis",MKHIS );
		scriptGroup.writeEntry ( "mkthis",MKTHIS );
		scriptGroup.writeEntry ( "mkehis",MKEHIS );
		scriptGroup.writeEntry ( "mksmap",MKSMAP );
		scriptGroup.writeEntry ( "mkrmap",MKRMAP );
		scriptGroup.writeEntry ( "mkrawnt",MKRWNT );
		scriptGroup.writeEntry ( "recon",RECON );
		scriptGroup.writeEntry ( "viewer",VIEWER );
		scriptGroup.writeEntry ( "plotter",PLOTTER );
		scriptGroup.writeEntry ( "plotster",PLOTSTER );
		scriptGroup.writeEntry ( "anaplotter",ANAPLOTTER );
		scriptGroup.writeEntry ( "runcom",RUNCOM );
	}

	if ( ! ( veto&CLE_EXT ) )
	{
		externalGroup.writeEntry ( "notice",NOTICE );
		externalGroup.writeEntry ( "find",FIND );
		externalGroup.writeEntry ( "Ana viewer",XMEDCON );
		externalGroup.writeEntry ( "Dicom viewer",AMIDE );
		externalGroup.writeEntry ( "Web browser",webbrowser );
	}

	if ( ! ( veto&CLE_MIS ) )
	{
		miscGroup.writeEntry ( "Auto set extension",autoExtBox->isChecked() );
		miscGroup.writeEntry ( "Allow overwrite",overwriteBox->isChecked() );
		miscGroup.writeEntry ( "Ignore file type",ignoreFiletypeBox->isChecked() );
		miscGroup.writeEntry ( "Notify when done",noticeBox->isChecked() );
		miscGroup.writeEntry ( "Open when done",automaticViewBox->isChecked() );

		miscGroup.writeEntry ( "Show file type",showFileTypeBox->isChecked() );
		miscGroup.writeEntry ( "Show file size",showFileSizeBox->isChecked() );
		miscGroup.writeEntry ( "Show last modified date",showLMDBox->isChecked() );
		miscGroup.writeEntry ( "Show last modified time",showLMTBox->isChecked() );
		miscGroup.writeEntry ( "Confirm on exit",confirmExitBox->isChecked() );
		miscGroup.writeEntry ( "Stay on top",stayTopBox->isChecked() );
		miscGroup.writeEntry ( "Remember file location",rememberFileLocBox->isChecked() );
		miscGroup.writeEntry ( "Auto set output filename",autoSetFilenameBox->isChecked() );

		miscGroup.writeEntry ( "Auto clear information",autoCleInfoBox->isChecked() );
		miscGroup.writeEntry ( "Need confirm on clear information",confirmCleInfoBox->isChecked() );
		miscGroup.writeEntry ( "Auto remove data",autoRemoveDataBox->isChecked() );
		miscGroup.writeEntry ( "Need confirm on remove data",confirmRemoveDataBox->isChecked() );

		miscGroup.writeEntry ( "Log enabled",logBut->isOn() );
	}

	histGroup.writeEntry ( "command history",runComBox->historyItems() );
	histGroup.writeEntry ( "command completion",runComBox->completionObject()->items() );

	histGroup.writeEntry ( "operator history",operatorBox->historyItems() );
	histGroup.writeEntry ( "operator completion",operatorBox->completionObject()->items() );

	histGroup.writeEntry ( "body part history",bodyPartBox->historyItems() );
	histGroup.writeEntry ( "body part completion",bodyPartBox->completionObject()->items() );

	histGroup.writeEntry ( "radiopharm history",rpBox->historyItems() );
	histGroup.writeEntry ( "radiopharm completion",rpBox->completionObject()->items() );

	histGroup.writeEntry ( "halflife history",halflifeBox->historyItems() );
	histGroup.writeEntry ( "halflife completion",halflifeBox->completionObject()->items() );

	switch ( recon_mode )
	{
		case RM_EMILY:
			histGroup.writeEntry ( "emilyOpt history",emilyOptBox->historyItems() );
			histGroup.writeEntry ( "emilyOpt completion",emilyOptBox->completionObject()->items() );
			break;
		case RM_MELIY:
			histGroup.writeEntry ( "meliyOpt history",emilyOptBox->historyItems() );
			histGroup.writeEntry ( "meliyOpt completion",emilyOptBox->completionObject()->items() );
			break;
		default:
			/*		reconGroup.writeEntry ( "Options for reconstruction",emilyOptBox->currentText() );
					reconGroup.writeEntry("Arguments for reconstruction",THEARGS);*/
			break;
	}

	generalGroup.sync();
	scriptGroup.sync();
	externalGroup.sync();
	miscGroup.sync();
	histGroup.sync();

	delete conf;
}

void rp3dReconCls::setPcc()
{
	if ( pcc!=NULL )
	{
		disconnect ( pcc, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdoutc() ) );
		disconnect ( pcc, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrc() ) );
		disconnect ( pcc, SIGNAL ( processExited() ), this,  SLOT ( comDone() ) );
		delete pcc;
	}
	pcc = new QProcess ( this );
	connect ( pcc, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdoutc() ) );
	connect ( pcc, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrc() ) );
	connect ( pcc, SIGNAL ( processExited() ), this,  SLOT ( comDone() ) );
}

rp3dReconCls::rp3dReconCls ( QWidget *parent, const char *name )
		:rp3dReconDlg ( parent, name )
		,pcm ( NULL ),pce ( NULL ),pcv ( NULL ),pcs ( NULL ),pcc ( NULL )
		,tpcm ( NULL ),tpce ( NULL ),tpcs ( NULL )
		,ecm ( 0 ),ece ( 0 ),ecs ( 0 )
		,flipm ( 0 ),flipe ( 0 ),flips ( 0 )
		,numsel ( 0 ),numlf ( 0 ),numhf ( 0 ),numxf ( 0 ),numlft ( 0 ),numhft ( 0 ),numxft ( 0 )
		,killedm ( false ),killede ( false ),killeds ( false )
		,showhdr ( true ),showsize ( true ),showlastmodify ( true ),showlastmodifyt ( false )
		,lastdir ( "" ),lastrdir ( "" ),lastsdir ( "" ),lastodir ( "" ),fouth ( "" ),fout ( "" )
		,indxh ( -1 ),indxl ( -1 )
		,mkhisobj ( 0 ),noupdatebut ( false ),pid ( 0 ),uid ( 0 )
		,selectMulti ( false )
{

khcs[KHC_OPERATOR]=operatorBox;
khcs[KHC_BODYPART]=bodyPartBox;
khcs[KHC_RP]      =rpBox;
khcs[KHC_HALFLIFE]=halflifeBox;
khcs[KHC_OPT]     =emilyOptBox;
khcs[KHC_COM]     =runComBox;

	setmanw=NULL;
	iopCode="";

	msgBox->resize ( 700,msgBox->height() );//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	resize ( width(),820 );
	theBgCol=paletteBackgroundColor();

	QString s;
	QString cap="rp3dRecon ";
	QDate d = QDate::currentDate();
	QTime t = QTime::currentTime();
	size_t const shmsize=1024*1024*64;
	struct passwd *passwd; /* man getpwuid */

	this->setAcceptDrops ( TRUE );

	controlButs[0]=operationBut;
	controlButs[1]=settingsBut;
	controlButs[2]=findBut;
	controlButs[3]=runBut;
	controlButs[4]=etcBut;

	char pathname[1024];

	uid=getuid();
	passwd = getpwuid ( uid );
	pid=getpid();
	USER=passwd->pw_name;

	if ( pid2name ( pid,pathname ) ==0 )
	{
		s="rp3drecon";
	}
	else
	{
		s=pathname;
	}
	s+=" version ";
#ifdef VERSION
	s+=VERSION;
	cap+="version ";
	cap+=VERSION;
	cap+=" featuring ";
#else
	s+="unknown";
#endif

	printmsg ( "This is "+s );
	s.sprintf ( "Session opened: %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d by user %s [%d] ",d.year(),d.month(),d.day(),t.hour(),t.minute(),t.second(),USER.latin1(), pid );
	printmsg ( s );

	shmid=open_shm ( pathname, uid, shmsize );
	if ( shmid !=0 )
	{
		if ( shmid<0 )
		{
			if ( KMessageBox::No==KMessageBox::warningYesNo (
			            this,
			            tr ( "Exclusive use of the shared memory failed.\nYou may try 'ipcrm -W' before running.\nThe content will be overwritten by me.\n\nDo you want to continue?" ),
			            tr ( "Warning" ) ) )
				exit ( 1 );
		}
		QString str;
		put_shm ( ( int ) shmsize,0 );
		put_shm ( 0,8 );// number of blocks
		put_shm ( ( int ) shmsize-16,16 );// maxsize
		str.sprintf ( "shmat id = %d ready.",abs ( shmid ) );
		printmsg ( str );
		setenv ( "RP3SHMOFFIMAG","16",1 );
	}
	else
	{
		printmsg ( "Failed to allocate shared memory","red" );
		if ( KMessageBox::No==KMessageBox::warningYesNo (
		            this,
		            tr ( "Failed to allocate shared memory\nDo you want to continue?" ),
		            tr ( "Warning" ) ) )
			exit ( 1 );
	}

	CWD=getenv ( "PWD" );//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	HOME=getenv ( "HOME" );
	if ( HOME.isEmpty() )
		KMessageBox::error ( this, "We have no HOME!","ERROR" );
	loadConfig ( HOME+CONFIG );
	switch ( recon_mode )
	{
		case RM_EMILY:
			cap+="emily";
			break;
		case RM_MELIY:
			cap+="meliy";
			break;
		default:
			cap+=RECON;
			break;
	}
	setCaption ( cap );
	s=THEOPT;
	if ( s.isEmpty() ) s="(none)";
	printmsg ( "Options for reconstruction: "+s,"darkgreen" ,true );
	printmsg ( "Detector separation: "+QString::number ( detectorSeparationBox->value() ),"darkgreen" ,true );
	printmsg ( "Number of iteration: "+QString::number ( iteBox->value() ),"darkgreen" ,true );

	if ( DATA.isEmpty() ) DATA=CWD;
	if ( !dirExists ( DATA ) )
	{
		printmsg ( "Cannot access data direcotry: "+DATA,"red" );
		DATA=CWD;
	}
	else
	{
		QDir d;
		if ( !d.cd ( DATA ) ) printmsg ( "Cannot cd to data direcotry: "+DATA,"red" );
		DATA=CWD;
	}

	infdirBox->setText ( DATA );
	scrpathEdit->setText ( SCRPATH );
	printmsg ( "Checking scripts/binaries..." );
	check_scr_all();

	QPalette pal = infListBox->palette();
	pal.setColor ( QColorGroup::Highlight, qRgb ( 205,234,255 ) );
	pal.setColor ( QColorGroup::HighlightedText, qRgb ( 0,71,171 ) );
	infListBox->setPalette ( pal );

	bodyPartBox->setPalette ( pal );
	rpBox->setPalette ( pal );
	halflifeBox->setPalette ( pal );

	pal.setColor ( QColorGroup::Highlight, qRgb ( 233,255,244 ) );
	pal.setColor ( QColorGroup::HighlightedText, qRgb ( 19,135,77 ) );
	outfListBox->setPalette ( pal );
	emilyOptBox->setPalette ( pal );

	infListBox->setSelectionMode ( QListBox::Extended );
	labelwidth=hdrwidth+sizewidth+lastmodifywidth;

	dropeventveto=false;
	connect ( infListBox,SIGNAL ( dropped ( QDropEvent* ) ),this,SLOT ( recvDropped ( QDropEvent* ) ) );

	QToolTip::add ( cpuLbl,cpuLbl->cpu );

	controlStack->raiseWidget ( WID_OPERATION );
	currentPage=WID_OPERATION;
	operationBut->setOn ( true );
	switchButPal ( operationBut, true );

	dataListBox->setCurrentPage ( 1 );//<<<<<<<<<<<<<<<<<<<<<<<<<sc
	QTime ct=QDateTime::currentDateTime().time();
	QDate cd=QDateTime::currentDateTime().date();
	studyDateBox->setDate ( cd );
	startTimeBox->setTime ( ct );
	injectionTimeBox->setTime ( ct );
	dobBox->setDate ( cd );

	doseUnitBox->setCurrentItem ( 0 );
	currentDoseUnit=0;

	clearInfoBut->setEnabled ( false );

	if ( recon_mode==RM_MELIY )
	{
		fovRadBox->setEnabled ( true );
		lineIntBox->setEnabled ( true );
		MRPBox->setEnabled ( true );
		maxddBox->setEnabled ( true );
		// for the time being...
		senFileEdit->setEnabled ( false );
		uniFileEdit->setEnabled ( false );
		openSenFileBut->setEnabled ( false );
		openUniFileBut->setEnabled ( false );
		AAFBox->setEnabled ( false );
	}

	setPcc();

	pcm = new QProcess ( this );
	connect ( pcm, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdoutm() ) );
	connect ( pcm, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrm() ) );
	connect ( pcm, SIGNAL ( processExited() ), this,  SLOT ( convExited() ) );
	tpcm = new QTimer ( this );
	connect ( tpcm, SIGNAL ( timeout() ), this, SLOT ( pcmSlot() ) );

	pce = new QProcess ( this );
	connect ( pce, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdoute() ) );
	connect ( pce, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderre() ) );
	connect ( pce, SIGNAL ( processExited() ), this,  SLOT ( reconExited() ) );
	tpce = new QTimer ( this );
	connect ( tpce, SIGNAL ( timeout() ), this, SLOT ( pceSlot() ) );

	pcv = new QProcess ( this );
	connect ( pcv, SIGNAL ( processExited() ), this,  SLOT ( viewerDone() ) );

	pcs = new QProcess ( this );
	connect ( pcs, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdouts() ) );
	connect ( pcs, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrs() ) );
	connect ( pcs, SIGNAL ( processExited() ), this,  SLOT ( searchDone() ) );
	tpcs = new QTimer ( this );
	connect ( tpcs, SIGNAL ( timeout() ), this, SLOT ( pcsSlot() ) );

	lastimagefile="";
	lastimagefilefull="";

	theOks[0]=false;
	theOks[1]=false;
	theOks[2]=false;
	theOffs[0]=0;
	theOffs[1]=-10;
	theOffs[2]=-20;
	timerVeto=false;
	timerid=startTimer ( panelblinkinterval );
}

void rp3dReconCls::recvDropped ( QDropEvent *e )
{
	if ( dropeventveto ) return;
	dropEvent ( e );
}

size_t rp3dReconCls::getFileSize ( QString f )

{
	KURL url ( f );
	KFileItem item ( KFileItem::Unknown, KFileItem::Unknown, url );
	return ( size_t ) item.size();
}

QString rp3dReconCls::cfilesize ( size_t fs )
{
	float s;
	QString f="0";
	int const kb=1024;
	int const mb=kb*kb;
	int const gb=kb*kb*kb;
	s=fs;
	if ( s<kb )
	{
		f.sprintf ( "%5.1fB ",s );
	}
	else if ( s<mb )
	{
		f.sprintf ( "%5.1fK ",s/kb );
	}
	else if ( s<gb )
	{
		f.sprintf ( "%5.1fM ",s/mb );
	}
	else
	{
		f.sprintf ( "%5.1fG ",s/gb );
	}
	return f;
}

int rp3dReconCls::getFileType ( QString f, size_t *s )
{
	size_t fs;
	if ( f.startsWith ( "smb://" ) )
	{
		return FT_NSUP;
	}
	if ( !QFile::exists ( f ) )
	{
		KURL url ( f );
		KFileItem item ( KFileItem::Unknown, KFileItem::Unknown, url );
		if ( !item.isReadable() ) return FT_NENT;
		if ( !item.isFile() ) return FT_NFLE;
	}
	else if ( !QFileInfo ( f ).isFile() )
	{
		return FT_NFLE;
	}

	if ( f.endsWith ( ".dcm" ) ) return FT_DICM;//<<<<<<<<<<<<<<<<<<<<<<

	fs=getFileSize ( f );
	if ( s!=NULL ) *s=fs;
	if ( fs==hsizes[recon_mode] )
	{
		return FT_HIST;
	}
	else if ( fs>=lmdsizemin )
	{
		return FT_LIST;
	}
	else
	{
		return FT_NOP;
	}
}

void rp3dReconCls::printmsg ( QString s, QColor c, bool bold )
{

	msgBox->setBold ( bold );
	msgBox->setColor ( c );
	msgBox->append ( s );
	msgBox->setColor ( "black" );
}

void rp3dReconCls::proc_outf ( QString fn, int ft )
{
	QString f=fn;
	if ( showlastmodifyt||showlastmodify )
	{
		QDateTime lm = QFileInfo ( f ).lastModified();
		if ( showlastmodifyt ) ( f ).prepend ( lm.toString ( "hh:mm:ss " ) );
		if ( showlastmodify ) ( f ).prepend ( lm.toString ( "yyyy-MM-dd " ) );
	}
	if ( showsize )	( f ).prepend ( cfilesize ( getFileSize ( fn ) ) );
	if ( showhdr )
	{
		switch ( ft )
		{
			case FT_DICM:
				f.prepend ( lbl_dcm );
				break;
			case FT_HIST:
				f.prepend ( lbl_hst );
				break;
			case FT_IMAG:
				f.prepend ( lbl_img );
				break;
			case FT_PLOT:
				f.prepend ( lbl_plt );
				break;
			case FT_TEXT:
				f.prepend ( lbl_txt );
				break;
		}
	}
	outfListBox->insertItem ( f );
	if ( ft==FT_DICM ) lastoutimagefile=f.remove ( 0,labelwidth );
}

void rp3dReconCls::proc_infs ( QStringList *in, bool onTop )
{
	QString s;
	int ft;
	int k=-1;
	size_t fs;

	if ( in->count() ==0 ) return;
	if ( in->count() > NREGMAX )
	{
		k=0;
		regProgBar->setEnabled ( true );
		regProgBar->setTotalSteps ( in->count() );
		regProgBar->setProgress ( 0 );
	}
	for ( QStringList::Iterator it = in->begin(); it!=in->end(); ++it )
	{
		ft=getFileType ( *it , &fs );
		if ( ft == FT_NSUP )
		{
			printmsg ( "Unsupported protocol: "+ ( *it ),"red" );
			in->remove ( *it );
			continue;
		}
		if ( ft == FT_NFLE )
		{
			printmsg ( "Not a file: "+ ( *it ),"red" );
			in->remove ( *it );
			continue;
		}
		if ( ft == FT_NENT )
		{
			printmsg ( "File not found: "+ ( *it ),"red" );
			in->remove ( *it );
			continue;
		}
		if ( fs ==0 )
		{
			printmsg ( "File empty: "+ ( *it ),"red" );
			in->remove ( *it );
			continue;
		}

		if ( showlastmodifyt||showlastmodify )
		{
			QDateTime lm = QFileInfo ( *it ).lastModified();
			if ( showlastmodifyt ) ( *it ).prepend ( lm.toString ( "hh:mm:ss " ) );
			if ( showlastmodify ) ( *it ).prepend ( lm.toString ( "yyyy-MM-dd " ) );
		}
		if ( showsize )	( *it ).prepend ( cfilesize ( fs ) );
		QString f;
		if ( showhdr )
		{
			switch ( ft )
			{
				case FT_HIST:
					( *it ).prepend ( lbl_hst );
					numhft++;
					break;
				case FT_LIST:
					( *it ).prepend ( lbl_lst );
					numlft++;
					break;
				case FT_NOP:
					( *it ).prepend ( lbl_nop );
					numxft++;
					f= ( *it );
					printmsg ( "Unrecognized file type: "
					           + f.remove ( 0,labelwidth ),"red" );
					break;
			}
		}
		if ( k>=0 )
		{
			k++;
			regProgBar->setProgress ( k );
		}
	}
	if ( k>=0 )
	{
		regProgBar->setProgress ( 0 );
		regProgBar->setEnabled ( false );
	}
	noupdatebut=true;
	unsigned int i,i0=infListBox->count();
	if ( onTop )
	{
		infListBox->insertStringList ( *in, 0 );
	}
	else
	{
		infListBox->insertStringList ( *in );
		for ( i=i0;i<i0+in->count();i++ )
		{
			infListBox->setSelected ( i,true );
		}
	}
	noupdatebut=false;
	updateButSlot();
}

void rp3dReconCls::openFileSlot()
{
	QStringList infs = KFileDialog::getOpenFileNames ( outputPath(),
	                   "*.dat|Listmode data(*.dat)\n*.tmo|Histogram data (*.tmo)\n*.*|All (*.*)",
	                   this,
	                   tr ( "Select Input Data Files" ) );
	QStringList::Iterator it = infs.end();
// 	QStringList::Iterator it = infs.begin();
	lastdir= ( * ( --it ) ).section ( '/',-100,-2 );
	setOutputFilenameSlot();
	proc_infs ( &infs );
}

void rp3dReconCls::delSlot()
{
	int i;
	int m;

	if ( confirmRemoveDataBox->isChecked() )
	{
		if ( KMessageBox::Yes!=KMessageBox::warningYesNo (
		            this,
		            tr ( "Remove Selected Data ?" ),
		            tr ( "Warning" ) ) ) return;
	}

	m=0;
	noupdatebut=true;
	for ( i=infListBox->count()-1;i>=0;i-- )
	{
		if ( infListBox->isSelected ( i ) )
		{
			switch ( getFileType ( i ) )
			{
				case FT_HIST:
					numhft--;
					break;
				case FT_LIST:
					numlft--;
					break;
				case FT_NOP:
					numxft--;
					break;
			}
			m++;
			infListBox->removeItem ( i );
		}
	}
	noupdatebut=false;
	updateButSlot();
}

void rp3dReconCls::countSelectedItems()
{
	unsigned int i;
	QString f;
	numlf=0;
	numhf=0;
	numxf=0;
	numsel=0;
	indxh=-1;
	indxl=-1;
	for ( i=0;i<infListBox->count();i++ )
	{
		if ( infListBox->isSelected ( i ) )
		{
			numsel++;
			switch ( getFileType ( i ) )
			{
				case FT_HIST:
					if ( indxh==-1 ) indxh=i;
					numhf++;
					break;
				case FT_LIST:
					if ( indxl==-1 ) indxl=i;
					numlf++;
					break;
				case FT_NOP:
					numxf++;
					break;
			}
		}
	}
	f.sprintf ( "Entry: %d, H = %d, L = %d, X = %d (Selected: %d, H = %d, L = %d, X = %d)",
	            infListBox->count(),numhft,numlft,numxft,numsel,numhf, numlf,numxf );
	hdrLbl->setText ( f );
}

void rp3dReconCls::enableButSlot()
{
	if ( ignoreFiletypeBox->isChecked() )
	{
		if ( numsel!=0 )
		{
			mkhisBut->setEnabled ( true );
			reconBut->setEnabled ( true );
		}
	}
	else
	{
		doUpdateButSlot();
	}
}

void rp3dReconCls::doUpdateButSlot()
{
	if ( numsel ==0 )
	{
		deselBut->setEnabled ( false );
		mkhisBut->setEnabled ( false );
		reconBut->setEnabled ( false );
	}
	else
	{
		deselBut->setEnabled ( true );
		mkhisBut->setEnabled ( numlf>0 || ignoreFiletypeBox->isChecked() );
		reconBut->setEnabled ( numlf>0||numhf>0 || ignoreFiletypeBox->isChecked() );
	}
}

void rp3dReconCls::updateButSlot()
{
	if ( noupdatebut ) return;
	countSelectedItems();
	doUpdateButSlot();
}

void rp3dReconCls::cleSlot()
{
	unsigned int i;
	noupdatebut=true;
	for ( i=0;i<infListBox->count();i++ )
	{
		if ( infListBox->isSelected ( i ) ) infListBox->setSelected ( i,false );
	}
	noupdatebut=false;
	updateButSlot();
}

void rp3dReconCls::selectAllSlot()
{
	unsigned int i;
	noupdatebut=true;
	for ( i=0;i<infListBox->count();i++ )
	{
		if ( !infListBox->isSelected ( i ) ) infListBox->setSelected ( i,true );
	}
	noupdatebut=false;
	updateButSlot();
}

int  rp3dReconCls::setfout ( int type , QString *f )
{
	QString filter="*.*| Any files (*.*)";
	QLineEdit *lbl=NULL;
	QString ext;

	switch ( type )
	{
		case FT_HIST:
			if ( f->isEmpty() )
			{
				switch ( mkhisobj )
				{
					case MHO_HISTT:
					case MHO_HISTP:
					case MHO_HISTD:
						filter="*.tmo|Histogram file (*.tmo)\n*.*|Any (*.*)";
						break;
					case MHO_EHIS:
					case MHO_THIS:
					case MHO_RWNT:
						filter="*.txt|text file (*.txt)\n*.*|Any (*.*)";
						break;
					case MHO_SMAP:
					case MHO_RMAP:
						filter="*.img|image file (*.img)\n*.*|Any (*.*)";
						break;
				}
			}
			lbl=fhoutBox;
			switch ( mkhisobj )
			{
				case MHO_HISTT:
				case MHO_HISTP:
				case MHO_HISTD:
					ext=".tmo";
					break;
				case MHO_EHIS:
				case MHO_THIS:
				case MHO_RWNT:
					ext=".txt";
					break;
				case MHO_SMAP:
				case MHO_RMAP:
					ext=".img";
					break;
			}
			break;
		case FT_DICM:
			lbl=foutBox;
			ofmtid=ofmtBox->currentItem();
			switch ( ofmtid )
			{
				case OFMTID_DICOM:
					filter="*.dcm|DICOM file (*.dcm)";
					ext=".dcm";
					break;
				case OFMTID_ANALYZE:
					filter="*.img|analyze file (*.img)";
					ext=".img";
					break;
				case OFMTID_RAW:
					filter="*.img|raw file (*.img)";
					ext=".img";
					break;
			}
			filter=filter+"\n*.*|Any (*.*)";
			break;
	}

	QString theFile=f->copy().section ( "/",-1 );
	QString thePath=f->copy().section ( "/",0,-2 );

	if ( theFile.isEmpty() )
	{
		if ( thePath.isEmpty() ) thePath=outputPath();
		KFileDialog *fd = new KFileDialog ( thePath,filter,this,NULL,true );
		fd->setModal ( true );
		fd->setCaption ( "Save Output File As" );
		fd->setOperationMode ( KFileDialog::Saving );
		if ( !theFile.isEmpty() )
		{
			fd->setSelection ( theFile );
		}
		else if ( autoSetFilenameBox->isChecked() &&!lastimagefile.isEmpty() )
		{
			fd->setSelection ( lastimagefile );
		}
		fd->setMode ( KFile::File );
		if ( fd->exec() == KFileDialog::Accepted )
		{
			*f = fd->selectedFile();
		}
		delete fd;
	}
	if ( f->isEmpty() ) return 0;
	if ( f->section ( '/',-1,-1 ).isEmpty() ) return 0;
	lastodir = f->section ( '/',-100,-2 );

	if ( autoExtBox->isChecked() )
	{
		int extpos = f->findRev ( '.' ) ;
		int slashpos = f->findRev ( '/' );
		if ( extpos<slashpos ) extpos=-1;

		if ( extpos ==-1 )
		{
			f->append ( ext );
		}
		else if ( !f->endsWith ( ext ) )
		{
			int len=f->length()-extpos;
			f->remove ( extpos,len );
			f->append ( ext );
		}
		lbl->setText ( *f );
	}

	if ( !overwriteBox->isChecked() )
	{
		if ( QFile::exists ( *f ) )
		{
			if ( KMessageBox::Continue!=KMessageBox::warningContinueCancel (
			            this,
			            tr ( "A file %1 already exists.\nDo you want to overwrite it?" ).arg ( *f ),
			            tr ( "Warning" ) ) ) return 0;
		}
	}
	lbl->setText ( *f );
	return 1;
}

void rp3dReconCls::slotReadStdoutm()
{
	if ( nolm==-1 ) return;
	while ( pcm->canReadLineStdout() && ( ++nolm ) <=nol_max )
	{
		QString line ( pcm->readLineStdout() );
		msgBox->append ( line );
	}
	if ( nolm>nol_max )
	{
		msgBox->append ( "...skipped" );
		nolm=-1;
	}
}
void rp3dReconCls::slotReadStderrm()
{
	if ( nelm==-1 ) return;
	msgBox->setColor ( "red" );
	while ( pcm->canReadLineStderr() && ( ++nelm ) <=nel_max )
	{

		QString line ( pcm->readLineStderr() );
		msgBox->append ( line );
	}
	if ( nelm>nel_max )
	{
		msgBox->append ( "...skipped" );
		nelm=-1;
	}
	msgBox->setColor ( "black" );
}

void rp3dReconCls::slotReadStderre()
{
	if ( nele==-1 ) return;
	msgBox->setColor ( "red" );
	while ( pce->canReadLineStderr() && ( ++nele ) <=nel_max )
	{
		QString line ( pce->readLineStderr() );
		msgBox->append ( line );
	}
	if ( nele>nel_max )
	{
		msgBox->append ( "...skipped" );
		nele=-1;
	}
	msgBox->setColor ( "black" );//<<<<<<<<<<<<<<<
}

void rp3dReconCls::slotReadStdoute()
{
	if ( nole==-1 ) return;
	while ( pce->canReadLineStdout() && ( ++nole<=nol_max ) )
	{
		QString line ( pce->readLineStdout() );
		msgBox->append ( line );
	}
	if ( nole>nol_max )
	{
		msgBox->append ( "...skipped" );
		nole=-1;
	}
}

void rp3dReconCls:: runscr ( QString s, QString f, bool fullpath )
{
	QString c="";
	if ( !fullpath ) c=SCRPATH+"/";
	c=c+s+" "+"'"+f+"'"+"&";
	system ( c );
	printmsg ( c.prepend ( USER+"% " ) );
}

void rp3dReconCls::convExited()
{
	QString str;
	QString msg;
	QColor c;

	if ( pcm->isRunning() ) return;
	tpcm->stop();
	runmLed->setState ( KLed::Off );
	mkhisBut->setEnabled ( true );
	fhoutBox->setEnabled ( true );
	fhoutBox->setReadOnly ( false );
	selectfhoutBox->setEnabled ( true );
	openResultBut->setEnabled ( true );
	objBut->setEnabled ( true );
	killmBut->setEnabled ( false );

	flipm=0;
	msg="";
	if ( killedm )
	{
		ecm=-1;
		msg="aborted!";
	}
	else if ( !pcm->normalExit() )
	{
		ecm=-2;
		msg="killed!!";
	}
	else
	{
		ecm=pcm->exitStatus();
	}

	QStringList::Iterator it = pcm->arguments().begin();
	str= ( *it ) +" exited with code "+QString::number ( ecm );
	if ( ecm!=0 )
	{
		c="red";
		str+= " (failure)";
	}
	else
	{
		msg="finished.";
		str+=" (success)";
		int ft=0;
		c="blue";
		bool showresult;
		showresult=automaticViewBox->isChecked();
		QStringList sl;
		if ( mkhisobj!=MHO_HISTD && mkhisobj!=MHO_HISTP && mkhisobj!=MHO_HISTT && mkhisobj!=MHO_RWNT ) viewResultBut->setEnabled ( true );
		switch ( mkhisobj )
		{
			case MHO_HISTT:
			case MHO_HISTP:
			case MHO_HISTD:
				ft=FT_HIST;
				if ( fouth!=infListBox->text ( 0 ).remove ( 0,labelwidth ) )
				{
					sl<<fouth;
					proc_infs ( &sl,true );
				}
				break;
			case MHO_RWNT:
				ft=FT_TEXT;
				break;
			case MHO_THIS:
				ft=FT_PLOT;
				if ( showresult ) runscr ( PLOTTER,fouth );
				break;
			case MHO_EHIS:
				ft=FT_PLOT;
				if ( showresult ) runscr ( PLOTSTER,fouth );
				break;
			case MHO_RMAP:
				ft=FT_IMAG;
				if ( showresult ) runscr ( XMEDCON,fouth.replace ( "img","hdr",false ), true );
				break;
			case MHO_SMAP:
				ft=FT_IMAG;
				if ( showresult ) runscr ( ANAPLOTTER,fouth );
				break;
		}
		proc_outf ( fouth,ft );
	}
	if ( !killedm && noticeBox->isChecked() ) runscr ( NOTICE,msg,true );
	printmsg ( str,c );
	if ( !msg.isEmpty() ) printmsg ( "Conversion "+msg );
}

void rp3dReconCls::pcmSlot()
{
	if ( runmLed->state() ==KLed::Off )
	{
		runmLed->setState ( KLed::On );
	}
	else
	{
		flipm++;
		if ( flipm==2 )
		{
			runmLed->setState ( KLed::Off );
			flipm=0;
		}
	}
}

void rp3dReconCls::checkScrSlot()
{
	printmsg ( "Checking scripts/binaries..." );
	check_scr_all ( true );
}

void rp3dReconCls::echoBool ( QString m, int c,bool v )
{
	QColor col;
	QString stat;
	if ( c==0 )
	{
		col="blue";
		stat=" ===> ok";
	}
	else
	{
		stat=" ===> no";
		col="red";
	}
	if ( v||c!=0 ) printmsg ( m+stat,col );
}

void rp3dReconCls::check_scr_all ( bool v )
{
	int e=0, ee=0;
	echoBool ( MKHIS,     e=check_scr ( SCRPATH+"/"+MKHIS,true ),v );
	ee+=e;
	echoBool ( MKTHIS,    e=check_scr ( SCRPATH+"/"+MKTHIS,true ),v );
	ee+=e;
	echoBool ( MKEHIS,    e=check_scr ( SCRPATH+"/"+MKEHIS,true ),v );
	ee+=e;
	echoBool ( MKSMAP,    e=check_scr ( SCRPATH+"/"+MKSMAP,true ),v );
	ee+=e;
	echoBool ( MKRMAP,    e=check_scr ( SCRPATH+"/"+MKRMAP,true ),v );
	ee+=e;
	echoBool ( MKRWNT,    e=check_scr ( SCRPATH+"/"+MKRWNT,true ),v );
	ee+=e;
	echoBool ( RECON,     e=check_scr ( SCRPATH+"/"+RECON,true ),v );
	ee+=e;
	echoBool ( VIEWER,    e=check_scr ( SCRPATH+"/"+VIEWER,true ),v );
	ee+=e;
	echoBool ( PLOTTER,   e=check_scr ( SCRPATH+"/"+PLOTTER,true ),v );
	ee+=e;
	echoBool ( PLOTSTER,  e=check_scr ( SCRPATH+"/"+PLOTSTER,true ),v );
	ee+=e;
	echoBool ( ANAPLOTTER,e=check_scr ( SCRPATH+"/"+ANAPLOTTER,true ),v );
	ee+=e;
	echoBool ( RUNCOM,    e=check_scr ( SCRPATH+"/"+RUNCOM,true ),v );
	ee+=e;
	echoBool ( NOTICE,    e=check_scr ( NOTICE ,true ),v );
	ee+=e;
	echoBool ( FIND,      e=check_scr ( FIND ,true ),v );
	ee+=e;
	echoBool ( XMEDCON,   e=check_scr ( XMEDCON ,true ),v );
	ee+=e;
	echoBool ( AMIDE,     e=check_scr ( AMIDE ,true ),v );
	ee+=e;
	QString m="All scripts/binaries green.";
	QColor mc="blue";
	if ( ee!=0 )
	{
		m="Some scripts/binaries unusable";
		mc="red";
	}
	scrCheckLbl->setPaletteForegroundColor ( mc );
	scrCheckLbl->setText ( m );
	printmsg ( m,mc,true );
}

int rp3dReconCls::check_scr ( QString s, bool quiet )
{
	QString ss=s.copy().section ( " ",0,0 );
	if ( QFile::exists ( ss ) )
	{
		struct stat sb;
		stat ( ss.latin1(), &sb );
		if ( S_ISREG ( sb.st_mode ) && ( sb.st_mode & S_IXUSR ) )
		{
			return 0;
		}
		else
		{
			ss.prepend ( "Permission denied: " );
		}
	}
	else
	{
		ss.prepend ( "No such script/binary file: " );
	}
	if ( !quiet )
	{
		KMessageBox::error ( this, ss, "ERROR" );
		printmsg ( ss,"red" );
	}
	return 1;
}

void rp3dReconCls::mkhisSlot()
{
	QString f;
	unsigned int i;
	QString cmdline;
	QString s;
	bool ignoreft;
	mkhisobj=objBut->currentItem();
	switch ( mkhisobj )
	{
		case MHO_HISTT:
		case MHO_HISTP:
		case MHO_HISTD:
			s=MKHIS;
			break;
		case MHO_THIS:
			s=MKTHIS;
			break;
		case MHO_EHIS:
			s=MKEHIS;
			break;
		case MHO_SMAP:
			s=MKSMAP;
			break;
		case MHO_RMAP:
			s=MKRMAP;
			break;
		case MHO_RWNT:
			s=MKRWNT;
			break;
	}
	s=SCRPATH+"/"+s;

	if ( check_scr ( s ) !=0 ) return;

	fouth=fhoutBox->text();
	if ( !setfout ( FT_HIST, &fouth ) ) return;

	pcm->setWorkingDirectory ( QDir ( DATA ) );
	pcm->clearArguments();

	pcm->setArguments ( QStringList::split ( " ",s ) );
// 	pcm->addArgument ( s ); // name of the script

	switch ( mkhisobj )
	{
		case MHO_RMAP:
		case MHO_SMAP:
		case MHO_EHIS:
		case MHO_RWNT:
			pcm->addArgument ( fouth );
			break;
	}

	ignoreft=ignoreFiletypeBox->isChecked();
	for ( i=0;i<infListBox->count();i++ )
	{
		if ( infListBox->isSelected ( i ) )
		{
			f=infListBox->text ( i );
			f.remove ( 0, labelwidth );
			if ( getFileType ( i ) ==FT_LIST || ignoreft )
			{
				if ( QFile::exists ( f ) )
				{
					pcm->addArgument ( f );
				}
				else
				{
					infListBox->setSelected ( i,false );
					f.prepend ( "Excluded: File not found: " );
					printmsg ( f,"red" );
				}
			}
			else
			{
				infListBox->setSelected ( i,false );
				f.prepend ( "Excluded: File type mismatch: " );
				printmsg ( f,"red" );
			}
		}
	}
	if ( mkhisobj<=MHO_HISTD )
	{
		if ( mkhisobj==MHO_HISTT )
		{
			pcm->addArgument ( "-o" );
		}
		else if ( mkhisobj==MHO_HISTP )
		{
			pcm->addArgument ( "-p" );
		}
		else if ( mkhisobj==MHO_HISTD )
		{
			pcm->addArgument ( "-d" );
		}
		pcm->addArgument ( fouth );
	}
	else if ( mkhisobj==MHO_THIS )
	{
		pcm->addArgument ( "-o" );
		pcm->addArgument ( fouth );
	}

	QStringList list = pcm->arguments();
	QStringList::Iterator it = list.begin();
	cmdline="";
	while ( it != list.end() )
	{
		cmdline.append ( *it ).append ( ' ' );
		++it;
	}
	printmsg ( cmdline );
	mkhisBut->setEnabled ( false );
	fhoutBox->setEnabled ( false );
	fhoutBox->setReadOnly ( true );
	selectfhoutBox->setEnabled ( false );
	openResultBut->setEnabled ( false );
	objBut->setEnabled ( false );
	nelm=0;
	nolm=0;
	pcm->start();
	tpcm->start ( 214 );
	killedm=false;
	killmBut->setEnabled ( true );
}

void rp3dReconCls::pceSlot()
{
	if ( runeLed->state() ==KLed::Off )
	{
		runeLed->setState ( KLed::On );
	}
	else
	{
		flipe++;
		if ( flipe==2 )
		{
			runeLed->setState ( KLed::Off );
			flipe=0;
		}
	}
}
void rp3dReconCls::reconExited()
{
	QString str;
	QString msg="";
	QColor c;
	if ( pce->isRunning() ) return;
	tpce->stop();
	runeLed->setState ( KLed::Off );
	reconBut->setEnabled ( true );
	selectfoutBox->setEnabled ( true );
	foutBox->setReadOnly ( false );
	runeLed->setState ( KLed::Off );
	killeBut->setEnabled ( false );
	flipe=0;
	if ( killede )
	{
		ece=-1;
		msg="aborted!";
	}
	else if ( !pce->normalExit() )
	{
		// this case exitStatus may return 0
		msg="killed!!";
		ece=-2;
	}
	else
	{
		ece=pce->exitStatus();
	}

	QStringList::Iterator it = pce->arguments().begin();
	str= ( *it ) +" exited with code "+QString::number ( ece );

	if ( ece!=0 )
	{
		c="red";
		str += " (failure)";
	}
	else
	{
		msg+="finished.";
		str += " (success)";
		proc_outf ( fout,FT_DICM );
		if ( ofmtid==OFMTID_ANALYZE )
		{
			QString f=fout;
			proc_outf ( f.replace ( ".img",".hdr" ),FT_DICM );
		}
		if ( shmid!=0 ) viewBut->setEnabled ( true );
		if ( ofmtid!=OFMTID_RAW ) amideBut->setEnabled ( true ); // if amide exists!
		c="blue";
		if ( automaticViewBox->isChecked() )
		{
			viewBut->setOn ( true );
			viewSlot();
		}

		if ( autoRemoveDataBox->isChecked() ) delSlot();
		if ( autoCleInfoBox->isChecked() ) clearInfoSlot ( false );
	}
	if ( !killede && noticeBox->isChecked() ) runscr ( NOTICE,msg,true );
	printmsg ( str,c );
	if ( !msg.isEmpty() ) printmsg ( "Reconstruction "+msg );
}
void rp3dReconCls::reconSlot()
{
	QString f;
	QString s;
	unsigned int i;
	QString cmdline;
	int ft;
	bool ignoreft;

	s=SCRPATH+"/"+RECON;
	if ( check_scr ( s ) !=0 ) return;

	fout=foutBox->text();
	if ( !setfout ( FT_DICM, &fout ) ) return;

	commitInfoSlot();

	pce->setWorkingDirectory ( QDir ( DATA ) );
	pce->clearArguments();

	QString a=s;
	if ( !emilyOptBox->currentText().isEmpty() ) a+=" "+emilyOptBox->currentText();
	QStringList args=QStringList::split ( " ",a );

	pce->setArguments ( args );

	pce->addArgument ( "-D" );
	pce->addArgument ( detectorSeparationBox->text() );

	pce->addArgument ( "-N" );
	pce->addArgument ( iteBox->text() );

	pce->addArgument ( "--ofmt" );
	pce->addArgument ( ofmtBox->currentText() );

	pce->addArgument ( "-o" );
	pce->addArgument ( fout );

	if ( shmid!=0 )
	{
		pce->addArgument ( "-M" );
		pce->addArgument ( QString::number ( abs ( shmid ) ) );
	}

	if ( recon_mode==RM_EMILY )
	{
		if ( !uniFileEdit->text().isEmpty() )
		{
			pce->addArgument ( "-n" );
			pce->addArgument ( uniFileEdit->text() );
		}
		/*		if(senFileEdit->text().length()>0){
					pce->addArgument("-e");
					pce->addArgument(senFileEdit->text());
				}*/
		if ( AAFBox->value() >0 )
		{
			pce->addArgument ( "-F" );
			pce->addArgument ( QString::number ( AAFBox->value() ) );
		}
	}

	bool ok;
	float cf;
	cf=QString ( getenv ( "RP3CF" ) ).toFloat ( &ok );
	if ( ok&&cf!=1.0&&cf>0.0 )
	{
		pce->addArgument ( "--cf" );
		pce->addArgument ( getenv ( "RP3CF" ) );
	}

	if ( sThBox->value() >0 )
	{
		pce->addArgument ( "-p" );
		pce->addArgument ( QString::number ( sThBox->value() /100.0 ) );
	}

	if ( sliceThicknessBox->value() >1 )
	{
		pce->addArgument ( "-Z" );
		pce->addArgument ( QString::number ( sliceThicknessBox->value() ) );
	}

	if ( maxcdBox->value() >=0 )
	{
		pce->addArgument ( "-a" );
		pce->addArgument ( QString::number ( maxcdBox->value() ) );
	}

	if ( mrsBox->currentText().toInt() >1 )
	{
		pce->addArgument ( "-m" );
		pce->addArgument ( mrsBox->currentText() );
	}

	if ( recon_mode==RM_MELIY )
	{
		pce->addArgument ( "-R" );
		pce->addArgument ( QString::number ( fovRadBox->value() ) );
		if ( MRPBox->value() !=0 )
		{
			pce->addArgument ( "-b" );
			pce->addArgument ( QString::number ( MRPBox->value() ) );
		}
		if ( maxddBox->value() !=-1 )
		{
			pce->addArgument ( "-d" );
			pce->addArgument ( QString::number ( maxddBox->value() ) );
		}
		if ( lineIntBox->currentText().toInt() >1 )
		{
			pce->addArgument ( "-s" );
			pce->addArgument ( lineIntBox->currentText() );
		}
	}

	ignoreft=ignoreFiletypeBox->isChecked();
	for ( i=0;i<infListBox->count();i++ )
	{
		if ( infListBox->isSelected ( i ) )
		{
			f=infListBox->text ( i );
			f.remove ( 0, labelwidth );
			ft=getFileType ( i );
			if ( ft==FT_NOP && !ignoreft )
			{
				continue;
			}
			if ( !QFile::exists ( f ) )
			{
				infListBox->setSelected ( i,false );
				f.prepend ( "Excluded: File not found: " );
				printmsg ( f,"red" );
				continue;
			}
			switch ( ft )
			{
				case FT_HIST:
					pce->addArgument ( "-i" );
					break;
				case FT_LIST:
				default:
					pce->addArgument ( "-l" );
					break;
			}
			pce->addArgument ( f );
		}
	}

// 	if ( !emilyOptBox->currentText().isEmpty() )
// 	{
// 		pce->addArgument ( emilyOptBox->currentText() );
// 		emilyOptBox->addToHistory ( emilyOptBox->currentText() );
// 	}

	QStringList list = pce->arguments();
	QStringList::Iterator it = list.begin();
	cmdline="";
	while ( it != list.end() )
	{
		cmdline.append ( *it ).append ( ' ' );
		++it;
	}
	printmsg ( cmdline );
	reconBut->setEnabled ( false );
	selectfoutBox->setEnabled ( false );
	foutBox->setReadOnly ( true );
	nele=0;
	nole=0;
	pce->start();
	tpce->start ( 428 );
	killede=false;
	killeBut->setEnabled ( true );
}

void rp3dReconCls::setfhoutSlot()
{
	fouth="";
	fhoutBox->clear();
	setfout ( FT_HIST, &fouth );
}

void rp3dReconCls::setfoutSlot()
{
	fout="";
	foutBox->clear();
	setfout ( FT_DICM, &fout );
}

void rp3dReconCls::killeSlot()
{
	killede=true;
	pce->tryTerminate();
	QTimer::singleShot ( 1000,pce,SLOT ( kill() ) );
}

void rp3dReconCls::killmSlot()
{
	killedm=true;
	pcm->tryTerminate();
	QTimer::singleShot ( 1000, pcm, SLOT ( kill() ) );
}

void rp3dReconCls::revSlot()
{
	unsigned int i;
	noupdatebut=true;
	for ( i=0;i<infListBox->count();i++ )
	{
		infListBox->setSelected ( i, !infListBox->isSelected ( i ) );
	}
	noupdatebut=false;
	updateButSlot();
}

void rp3dReconCls::toggleShowFileTypeSlot()
{
	if ( showhdr )
	{
		removeLabelFromDataList ( LBL_HDR );
	}
	else
	{
		appendLabelToDataList ( LBL_HDR );
	}
}

void rp3dReconCls::toggleShowFileSizeSlot()
{
	if ( showsize )
	{
		removeLabelFromDataList ( LBL_SIZE );
	}
	else
	{
		appendLabelToDataList ( LBL_SIZE );
	}
}

void rp3dReconCls::toggleShowFileLMDSlot()
{
	if ( showlastmodify )
	{
		removeLabelFromDataList ( LBL_LASTMODIFY );
	}
	else
	{
		appendLabelToDataList ( LBL_LASTMODIFY );
	}
}

void rp3dReconCls::toggleShowFileLMTSlot()
{
	if ( showlastmodifyt )
	{
		removeLabelFromDataList ( LBL_LASTMODIFYT );
	}
	else
	{
		appendLabelToDataList ( LBL_LASTMODIFYT );
	}
}

void rp3dReconCls::toggleSelectionModeMul()
{
	selectMulti=true;
	infListBox->setSelectionMode ( QListBox::Multi );
}
void rp3dReconCls::toggleSelectionModeExt()
{
	selectMulti=false;
	infListBox->setSelectionMode ( QListBox::Extended );
}

void rp3dReconCls::infRBClickSlot ( QListBoxItem* it, const QPoint&p )
{
	int sftid,sfsid,sflmdid,sflmtid;
	int smmid,smeid;
	QPopupMenu options ( this );
	options.setCheckable ( TRUE );
	options.setCaption ( "Options" );
	sftid=options.insertItem ( "file type", this, SLOT ( toggleShowFileTypeSlot() ) );
	sfsid=options.insertItem ( "file size", this, SLOT ( toggleShowFileSizeSlot() ) );
	sflmdid=options.insertItem ( "file date", this, SLOT ( toggleShowFileLMDSlot() ) );
	sflmtid=options.insertItem ( "file time", this, SLOT ( toggleShowFileLMTSlot() ) );
	options.insertSeparator();
	smmid=options.insertItem ( "Select Multi", this, SLOT ( toggleSelectionModeMul() ) );
	smeid=options.insertItem ( "Select Extend", this, SLOT ( toggleSelectionModeExt() ) );

	options.setItemChecked ( sftid,showhdr );
	options.setItemChecked ( sfsid,showsize );
	options.setItemChecked ( sflmdid,showlastmodify );
	options.setItemChecked ( sflmtid,showlastmodifyt );
	options.setItemChecked ( smmid, selectMulti );
	options.setItemChecked ( smeid, !selectMulti );

	options.exec ( p );
}

void rp3dReconCls::mouseReleaseEvent ( QMouseEvent *e )
{
	QPopupMenu menu ( this );
	if ( e->button() ==RightButton )
	{
		menu.insertItem ( QPixmap ( icon_help ), "About",this,SLOT ( showAbout() ) );
		menu.insertSeparator();
		menu.insertSeparator();
		menu.insertSeparator();
		menu.insertItem ( QPixmap ( icon_exit ),"Quit",this,SLOT ( close() ) );
		menu.exec ( e->globalPos() );
	}
}

void rp3dReconCls::showAbout()
{
	aboutcls *subWin;
	subWin = new aboutcls();
	subWin->wb=webbrowser;
	subWin->exec();
	delete subWin;
}

void rp3dReconCls::amideSlot()
{
	QString f=fout;

	if ( ofmtid==OFMTID_ANALYZE ) f.replace ( ".img",".hdr" );
	runscr ( AMIDE,f, true );
}

void rp3dReconCls::viewerDone()
{
	viewBut->setOn ( false );
}

void rp3dReconCls::viewSlot()
{
	QString f;
	if ( viewBut->state() ==QButton::On )
	{
		f=SCRPATH+"/"+VIEWER;
		if ( check_scr ( f ) !=0 )  return;
		pcv->setWorkingDirectory ( QDir ( HOME ) );
		pcv->clearArguments();
		pcv->addArgument ( f );
		pcv->addArgument ( QString::number ( abs ( shmid ) ) );
		pcv->addArgument ( "16" ); // offset to image block
		pcv->addArgument ( "2" );
		pcv->start();
	}
	else
	{
		pcv->tryTerminate();
		QTimer::singleShot ( 5000, pcv, SLOT ( kill() ) );
	}
}

void rp3dReconCls::keyPressEvent ( QKeyEvent *e )
{
int ic;
	if ( e->state() & ( Qt::ControlButton ) )
	{
		switch ( e->key() )
		{
			case Qt::Key_A:
				selectAllSlot();
				break;
			case Qt::Key_R:
				revSlot();
				break;
			case Qt::Key_C:
				cleSlot();
				break;
			case Qt::Key_O:
				openFileSlot();
				break;
			case Qt::Key_X:
				delSlot();
				break;
			case Qt::Key_L:
				for(ic=0;ic<NUM_KHCS;ic++){
					if(khcs[ic]->hasFocus()&&(!khcs[ic]->currentText().isEmpty())){
						khcs[ic]->removeFromHistory(khcs[ic]->currentText());
						khcs[ic]->lineEdit()->clear();
						break;
					}
				}
				break;
		}
	}
	else
	{
		switch ( e->key() )
		{
			case Qt::Key_A:
				openFileSlot();
				break;
			case Qt::Key_Q:
			case Qt::Key_Escape:
				close();
				break;
			case Qt::Key_O:
				controlButs[WID_OPERATION]->toggle();
				switchControl ( WID_OPERATION );
				break;
			case Qt::Key_S:
				controlButs[WID_SETTINGS]->toggle();
				switchControl ( WID_SETTINGS );
				break;
			case Qt::Key_F:
				controlButs[WID_FIND]->toggle();
				switchControl ( WID_FIND );
				break;
			case Qt::Key_R:
				controlButs[WID_RUN]->toggle();
				switchControl ( WID_RUN );
				break;
			case Qt::Key_E:
				controlButs[WID_ETC]->toggle();
				switchControl ( WID_ETC );
				break;
			case Qt::Key_L:
				logBut->toggle();
				logSlot();
				break;
		}
	}
}

void rp3dReconCls::runSearchSlot()
{
	if ( !searchBut->isOn() )
	{
		searchBut->setOn ( true );
		searchSlot();
	}
}

void rp3dReconCls::searchSlot()
{
	if ( !searchBut->isOn() )
	{
		killsearchSlot();
		return;
	}
	if ( searchBut->isOn() )
	{
		if ( check_scr ( FIND ) !=0 )
		{
			searchBut->setOn ( false );
			return;
		}
	}
	pcs->setWorkingDirectory ( QDir ( HOME ) );
	pcs->clearArguments();
	pcs->addArgument ( FIND );
	pcs->addArgument ( "-H" );
	if ( infdirBox->text().isEmpty() )
	{
		infdirBox->setText ( "/" );
	}
	pcs->addArgument ( infdirBox->text() );
	pcs->addArgument ( "-type" );
	pcs->addArgument ( "f" );
	if ( !filterBox->text().isEmpty() )
	{
		if ( casesensitiveBox->isChecked() )
		{
			pcs->addArgument ( "-name" );
		}
		else
		{
			pcs->addArgument ( "-iname" );
		}
		pcs->addArgument ( filterBox->text() );
	}

	sinfs.clear();
	foundLbl->clear();
	killsearchBut->setEnabled ( true );
	regsearchBut->setEnabled ( false );
	flips=0;
	nels=0;
	nols=0;
	tpcs->start ( 100 );
	searchBut->setText ( "Searching..." );
	bgcolo=searchBut->paletteBackgroundColor();
	killeds=false;
	pcs->start();
}

void rp3dReconCls::pcsSlot()
{
	int r,g,b;
	int const maxflip=20;
	float z= ( float ) abs ( flips ) / ( float ) maxflip;
	flips++;
	if ( z>=0.84 )
	{
		if ( flips>0 ) flips=-maxflip;
		z=0.84;
	}
	r=bgcolo.red() *z;
	g=bgcolo.green() *z;
	b=bgcolo.blue() *z;
	QColor fg ( r,g,b );
	searchBut->setPaletteForegroundColor ( fg );
}

void rp3dReconCls::slotReadStdouts()
{
	while ( pcs->canReadLineStdout() )
	{
		QString line ( pcs->readLineStdout() );
		sinfs+=line;
		if ( nols==-1 ) continue;
		nols++;
		if ( nols<=nol_max ) msgBox->append ( line );
	}
	if ( nols>nol_max )
	{
		msgBox->append ( "...skipped" );
		nols=-1;
	}
}
void rp3dReconCls::slotReadStderrs()
{
	if ( nels==-1 ) return;
	msgBox->setColor ( "red" );
	while ( pcs->canReadLineStderr() && ( ++nels ) <=nel_max )
	{
		QString line ( pcs->readLineStderr() );
		msgBox->append ( line );
	}
	if ( nels>nel_max )
	{
		msgBox->append ( "...skipped" );
		nels=-1;
	}
	msgBox->setColor ( "black" );
}

void rp3dReconCls::searchDone()
{
	QString str;
	QColor c;
	if ( killeds )
	{
		ecs=-1;
	}
	else
	{
		ecs=pcs->exitStatus();
	}
	str="Found";
	if ( sinfs.count() ==0 )
	{
		str+=" no";
	}
	else
	{
		str+=" "+QString::number ( sinfs.count() );
	}
	str += " match";
	if ( sinfs.count() !=1 ) str+="es";

	//	str.sprintf ( "Found %d matchs", ( int ) sinfs.count() );
	foundLbl->setText ( str );
	printmsg ( str );
	if ( sinfs.count() >0 ) regsearchBut->setEnabled ( true );
	//	str.sprintf ( "%d",ecs );
	str = "find exited with code "+QString::number ( ecs );
	if ( ecs==0 )
	{
		c="blue";
	}
	else
	{
		c="red";
	}
	printmsg ( str,c );
	tpcs->stop();
	searchBut->setOn ( false );
	killsearchBut->setEnabled ( false );
	searchBut->setText ( "Search" );
	searchBut->setPaletteForegroundColor ( "black" );
}

void rp3dReconCls::killsearchSlot()
{
	killeds=true;
	pcs->tryTerminate();
	QTimer::singleShot ( 5000,pcs,SLOT ( kill() ) );
}

void rp3dReconCls::regSlot()
{
	if ( sinfs.count() ==0 ) return;
	if ( sinfs.count() >NREGMAX )
	{
		if ( KMessageBox::Cancel==KMessageBox::warningContinueCancel (
		            this,
		            tr ( "Too many files to register: %1\nIt'll take long time\nAre You Sure?" )
		            .arg ( sinfs.count() ),
		            tr ( "Warning" ) ) ) return;
		regProgBar->setEnabled ( true );
	}
	proc_infs ( &sinfs );
	regsearchBut->setEnabled ( false );
}

bool rp3dReconCls::fileExists ( QString f )
{
	if ( QFile::exists ( f ) &&QFileInfo ( f ).isFile() ) return true;
	return false;
}
bool rp3dReconCls::dirExists ( QString d )
{
	if ( QFile::exists ( d ) &&QFileInfo ( d ).isDir() ) return true;
	return false;
}

void rp3dReconCls::infdirSlot()
{
	if ( !dirExists ( infdirBox->text() ) )
	{
		infdirBox->setPaletteForegroundColor ( "red" );
	}
	else
	{
		infdirBox->setPaletteForegroundColor ( "black" );
	}
}

void rp3dReconCls::datapathSlot()
{
	if ( !dirExists ( datapathEdit->text() ) )
	{
		datapathEdit->setPaletteForegroundColor ( "red" );
	}
	else
	{
		datapathEdit->setPaletteForegroundColor ( "black" );
		DATA=datapathEdit->text();
// 		infdirBox->setText ( DATA );
	}
}
void rp3dReconCls::scrpathSlot()
{
	scrCheckLbl->clear();
	if ( !dirExists ( scrpathEdit->text() ) )
	{
		scrpathEdit->setPaletteForegroundColor ( "red" );
		checkScrBut->setEnabled ( false );
	}
	else
	{
		scrpathEdit->setPaletteForegroundColor ( "black" );
		SCRPATH=scrpathEdit->text();
		checkScrBut->setEnabled ( true );
	}
}

void rp3dReconCls::openDataDirSlot()
{
	QString s;
	s=KFileDialog::getExistingDirectory ( DATA,this,tr ( "Choose a default data directory" ) );
	if ( !s.isEmpty() )
	{
		datapathEdit->setText ( s );
		DATA=s;
// 		infdirBox->setText ( DATA );
	}
}

void rp3dReconCls::openScrpathSlot()
{
	QString s;
	s=KFileDialog::getExistingDirectory ( SCRPATH,this,tr ( "Choose a script direcotry" ) );
	if ( !s.isEmpty() )
	{
		scrpathEdit->setText ( s );
		SCRPATH=s;
	}
}

void rp3dReconCls::opendirSlot()
{
	if ( lastsdir.isEmpty() ) lastsdir=DATA;
	QString infdir = KFileDialog::getExistingDirectory ( lastsdir, this,tr ( "Choose a search directory" ) );
	if ( infdir.isEmpty() ) return;
	infdirBox->setText ( infdir );
	lastsdir= infdir.section ( '/',-100,-1 );
}

void rp3dReconCls::viewResultSlot()
{
	QString c;
	QString f=fhoutBox->text();
	if ( f.isEmpty() ) return;
	if ( !fileExists ( f ) ) return;

	switch ( objBut->currentItem() )
	{
		case MHO_EHIS:
			runscr ( PLOTSTER,f );
			break;
		case MHO_THIS:
			runscr ( PLOTTER,f );
			break;

		case MHO_RMAP:
// fouth must always end with .img
			runscr ( XMEDCON,f.replace ( "img","hdr",false ), true );
			break;

		case MHO_SMAP:
			runscr ( ANAPLOTTER,f );
			break;

		default:
			return;
	}
}

void rp3dReconCls::openResultSlot()
{
	if ( lastrdir.isEmpty() ) lastrdir=DATA;
	QString f="";
	QString const hf="*.tmo|Histogram (*.tmo)";
	QString const af="*.*|All (*.*)";
	QString const tf="*.txt|Time Spectrum data (*.txt)";
	QString const mf="*.img|2D-MAP or Sensitivity (*.img)";
	switch ( objBut->currentItem() )
	{
		case MHO_HISTT:
		case MHO_HISTP:
		case MHO_HISTD:
			f=hf+"\n"+tf+"\n"+mf;
			break;
		case MHO_THIS:
		case MHO_EHIS:
			f=tf+"\n"+mf+"\n"+hf;
			break;
		case MHO_SMAP:
		case MHO_RMAP:
			f=mf+"\n"+tf+"\n"+hf;
			break;
	}
	f=f+"\n"+af;
	QString fin = KFileDialog::getOpenFileName ( lastrdir,
	              f,
	              this,
	              tr ( "Select an Input Data File" ) );
	if ( fin.isEmpty() ) return;
	fhoutBox->setText ( fin );
	lastrdir= fin.section ( '/',-100,-2 );
}

void rp3dReconCls::canViewSlot()
{
	viewResultBut->setEnabled (
	    ( ( ( mkhisobj=objBut->currentItem() ) != MHO_HISTT ) &&
	      ( ( mkhisobj=objBut->currentItem() ) != MHO_HISTP ) &&
	      ( ( mkhisobj=objBut->currentItem() ) != MHO_HISTD ) &&
	      ( fileExists ( fhoutBox->text() ) ) )
	);
}

void rp3dReconCls::selectHSlot()
{
	unsigned int i;
	for ( i=0;i<infListBox->count();i++ )
		infListBox->setSelected ( i, ( getFileType ( i ) ==FT_HIST ) );
}
void rp3dReconCls::selectLSlot()
{
	unsigned int i;
	for ( i=0;i<infListBox->count();i++ )
		infListBox->setSelected ( i, ( getFileType ( i ) ==FT_LIST ) );
}
void rp3dReconCls::selectXSlot()
{
	unsigned int i;
	for ( i=0;i<infListBox->count();i++ )
		infListBox->setSelected ( i, ( getFileType ( i ) ==FT_NOP ) );
}

// for input file list
int rp3dReconCls::getFileType ( unsigned int i, size_t * fs )
{
	if ( i>=infListBox->count() ) return -1;
	if ( !showhdr )
	{
		QString f= infListBox->text ( i ).remove ( 0,labelwidth );
		return getFileType ( f, fs );
	}

	QString label=infListBox->text ( i ).left ( 4 );
	if ( label==lbl_hst )
	{
		return FT_HIST;
	}
	else if ( label==lbl_lst )
	{
		return FT_LIST;
	}
	else if ( label==lbl_nop )
	{
		return FT_NOP;
	}
	else
	{
		return -1;
	}
}

void rp3dReconCls::doSort ( bool dir )
{
	switch ( dataListBox->currentPageIndex() )
	{
		case 0:
			infListBox->sort ( dir );
			break;
		case 1:
			outfListBox->sort ( dir );
			break;
	}
}

void rp3dReconCls::sortUpSlot()
{
	doSort ( false );
}

void rp3dReconCls::sortDownSlot()
{
	doSort ( true );
}

void rp3dReconCls::magSlot()
{
	QFont cf=infListBox->font();
	int ps=cf.pointSize();
	if ( ps>=fontsizemax ) return;
	cf.setPointSize ( ps+1 );
	infListBox->setFont ( cf );
	msgBox->setFont ( cf );
	outfListBox->setFont ( cf );
}

void rp3dReconCls::redSlot()
{
	QFont cf=infListBox->font();
	int ps=cf.pointSize();
	if ( ps<=fontsizemin ) return;
	cf.setPointSize ( ps-1 );
	infListBox->setFont ( cf );
	msgBox->setFont ( cf );
	outfListBox->setFont ( cf );
}

void rp3dReconCls::killComSlot()
{
	pcc->tryTerminate();
	QTimer::singleShot ( 5000,pcc,SLOT ( kill() ) );
}
void rp3dReconCls::runComSlot()
{
	if ( runComBox->currentText().isEmpty() ) return;

	if ( pcc->isRunning() )
	{
		if ( runComBut->text() == "Enter" )
		{
			pcc->writeToStdin ( runComBox->currentText() +"\n" );
			msgBox->moveCursor ( QTextEdit::MoveEnd,false );
			msgBox->insert ( runComBox->currentText() );
			runComBox->setCurrentText ( "" );
			return;
		}
		else
		{
			setPcc(); // <<<<<<<<<<<<<<
		}
	}
	QColor col;
	if ( runComBox->currentText() =="default" )
	{
		col = qRgb ( 239,239,239 ); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	}
	else
	{
		col = QColor ( runComBox->currentText() );
	}
	if ( col.isValid() )
	{
		if ( runComBox->currentText().at ( 0 ).category() ==QChar::Letter_Uppercase )
		{
			setPaletteForegroundColor ( col );
			controlStack->setPaletteForegroundColor ( col );
		}
		else
		{
			setPaletteBackgroundColor ( col );
			controlStack->setPaletteBackgroundColor ( col );
			QColor ledcol;
			ledcol=runmLed->color();
			runmLed->setColor ( col );
			runmLed->setPaletteForegroundColor ( col );
			runmLed->setPaletteBackgroundColor ( col );
			runmLed->setColor ( ledcol );
			ledcol=runeLed->color();
			runeLed->setColor ( col );
			runeLed->setPaletteForegroundColor ( col );
			runeLed->setPaletteBackgroundColor ( col );
			runeLed->setColor ( ledcol );
			theBgCol=col;
		}
		runComBox->clear();
		return;
	}

	QString com;
	com = SCRPATH+"/"+RUNCOM;
	if ( check_scr ( com ) !=0 ) return;

	pcc->clearArguments();
	pcc->setWorkingDirectory ( QDir ( HOME ) );
	pcc->addArgument ( com );

	com=runComBox->currentText().stripWhiteSpace();
	if ( com.length() ==0 ) return;
	bool bgjob=false;
	if ( com.endsWith ( "&" ) )
	{
		if ( com.length() ==1 ) return;
		bgjob=true;
	}
	runComBox->addToHistory ( com );
	if ( bgjob ) com = com.left ( com.length()-1 );

	int pf=com.find ( "$F" );
	if ( pf>=0 )
	{
		if ( pf!=0 ) pcc->addArgument ( com.left ( pf-1 ) );
		unsigned int i;
		QString f;
		QListBox *flist=NULL;
		switch ( dataListBox->currentPageIndex() )
		{
			case 0:
				break;
			case 1:
				flist = infListBox;
				break;
			case 2:
				flist = outfListBox;
				break;
		}
		if ( flist!=NULL )
		{
			for ( i=0;i<flist->count();i++ )
			{
				if ( flist->isSelected ( i ) )
				{
					f=flist->text ( i );
					pcc->addArgument ( f.remove ( 0,labelwidth ) );
				}
			}
		}
	}
	else
	{
		pcc->addArgument ( com );
	}
	printmsg ( USER+"% "+com );
	runComBox->setCurrentText ( "" );
	nelc=0;
	nolc=0;
	pcc->start();
	if ( !bgjob )
	{
		runComBut->setText ( "Enter" );
		killComBut->setEnabled ( true );
	}
}

void rp3dReconCls::comDone()
{
	runComBut->setText ( "Run" );
	killComBut->setEnabled ( false );
}

void rp3dReconCls::slotReadStderrc()
{
	if ( nelc==-1 ) return;
	msgBox->setColor ( "red" );
	while ( pcc->canReadLineStderr() && ( ++nelc ) <=nel_max )
	{
		QString line ( pcc->readLineStderr() );
		msgBox->append ( line );
	}
	if ( nelc>nel_max )
	{
		msgBox->append ( "...skipped" );
		nelc=-1;
	}
	msgBox->setColor ( "black" );
}
void rp3dReconCls::slotReadStdoutc()
{
	QByteArray a=pcc->readStdout();
	for ( int i=0;i<a.size();i++ )
	{
		if ( a[i]==0x0d ) a[i]=0x20;
	}
	msgBox->append ( a );
}

void rp3dReconCls::appendSize ( int s, QListBox*b )
{
	unsigned int i;
	QString f;
	bool sel;
	for ( i=0;i<b->count();i++ )
	{
		f=b->text ( i ).remove ( 0,labelwidth );
		sel=b->isSelected ( i );
		b->changeItem ( b->text ( i ).insert ( s,cfilesize ( QFile ( f ).size() ) ),i );
		if ( sel ) b->setSelected ( i,true );
	}
}
void rp3dReconCls::appendHdr ( QListBox *b )
{
	bool sel;
	QString f;
	QString lbl;
	unsigned int i;
	for ( i=0;i<b->count();i++ )
	{
		sel=b->isSelected ( i );
		f=b->text ( i ).remove ( 0,labelwidth );
		switch ( getFileType ( f ) )
		{
			case FT_HIST:
				lbl=lbl_hst;
				break;
			case FT_LIST:
				lbl=lbl_lst;
				break;
			case FT_NOP:
				lbl=lbl_nop;
				break;
			default:
				lbl=lbl_unknown;
				break;
		}
		b->changeItem ( b->text ( i ).prepend ( lbl ),i );
		if ( sel ) b->setSelected ( i,true );
	}
}
void rp3dReconCls::appendLastmodify ( int s, QListBox*b )
{
	unsigned int i;
	bool sel;
	QString f;
	for ( i=0;i<b->count();i++ )
	{
		sel=b->isSelected ( i );
		f=b->text ( i ).remove ( 0,labelwidth );
		b->changeItem ( b->text ( i ).insert ( s,QFileInfo ( f ).lastModified().toString ( "yyyy-MM-dd " ) ),i );
		if ( sel ) b->setSelected ( i,true );
	}

}
void rp3dReconCls::appendLastmodifyt ( int s, QListBox *b )
{
	unsigned int i;
	bool sel;
	QString f;
	for ( i=0;i<b->count();i++ )
	{
		sel=b->isSelected ( i );
		f=b->text ( i ).remove ( 0,labelwidth );
		b->changeItem ( b->text ( i ).insert ( s,QFileInfo ( f ).lastModified().toString ( "hh:mm:ss " ) ),i );
		if ( sel ) b->setSelected ( i,true );
	}
}

void rp3dReconCls::appendLabelToDataList ( int c )
{
	int s;
	QString f;
	QDateTime lm;
	noupdatebut=true;
	s=0;
	switch ( c )
	{
		case LBL_SIZE:
			if ( showhdr ) s+=hdrwidth;
			appendSize ( s,infListBox );
			appendSize ( s,outfListBox );
			showsize=true;
			showFileSizeBox->setChecked ( showsize );
			break;

		case LBL_HDR:
			appendHdr ( infListBox );
			appendHdr ( outfListBox );
			showhdr=true;
			showFileTypeBox->setChecked ( showhdr );
			break;

		case LBL_LASTMODIFY:
			if ( showhdr ) s+=hdrwidth;
			if ( showsize ) s+=sizewidth;
			appendLastmodify ( s, infListBox );
			appendLastmodify ( s, outfListBox );
			showlastmodify=true;
			showLMDBox->setChecked ( showlastmodify );
			break;

		case LBL_LASTMODIFYT:
			if ( showhdr ) s+=hdrwidth;
			if ( showsize ) s+=sizewidth;
			if ( showlastmodify ) s+=lastmodifywidth;
			appendLastmodifyt ( s,infListBox );
			appendLastmodifyt ( s,outfListBox );
			showlastmodifyt=true;
			showLMTBox->setChecked ( showlastmodifyt );
			break;
	}
	setLabelwidth();
	noupdatebut=false;
}

void rp3dReconCls::setLabelwidth()
{
	labelwidth=0;
	if ( showhdr ) labelwidth+=hdrwidth;
	if ( showsize ) labelwidth+=sizewidth;
	if ( showlastmodify ) labelwidth+=lastmodifywidth;
	if ( showlastmodifyt ) labelwidth+=lastmodifytwidth;
}

void rp3dReconCls::removeLbl ( int s, int w, QListBox*b )
{
	unsigned int i;
	bool sel;
	for ( i=0;i<b->count();i++ )
	{
		sel=b->isSelected ( i );
		b->changeItem ( b->text ( i ).remove ( s,w ),i );
		if ( sel ) b->setSelected ( i,true );
	}
}

void rp3dReconCls::removeLabelFromDataList ( int c )
{
	int w, s;
	s=0;w=0;
	switch ( c )
	{
		case LBL_SIZE:
			w=sizewidth;
			if ( showhdr ) s+=hdrwidth;
			showsize=false;
			showFileSizeBox->setChecked ( showsize );
			break;
		case LBL_LASTMODIFY:
			w=lastmodifywidth;
			if ( showhdr ) s+=hdrwidth;
			if ( showsize ) s+=sizewidth;
			showlastmodify=false;
			showLMDBox->setChecked ( showlastmodify );
			break;
		case LBL_HDR:
			w=hdrwidth;
			showhdr=false;
			showFileTypeBox->setChecked ( showhdr );
			break;
		case LBL_LASTMODIFYT:
			w=lastmodifytwidth;
			if ( showhdr ) s+=hdrwidth;
			if ( showsize ) s+=sizewidth;
			if ( showlastmodify ) s+=lastmodifywidth;
			showlastmodifyt=false;
			showLMTBox->setChecked ( showlastmodifyt );
			break;
	}
	noupdatebut=true;
	removeLbl ( s,w,infListBox );
	removeLbl ( s,w,outfListBox );
	setLabelwidth();
	noupdatebut=false;
}

void rp3dReconCls::showFileTypeSlot()
{
	if ( showFileTypeBox->isChecked() ==showhdr ) return;
	if ( showhdr )
	{
		removeLabelFromDataList ( LBL_HDR );
	}
	else
	{
		appendLabelToDataList ( LBL_HDR );
	}
}

void rp3dReconCls::showFileSizeSlot()
{
	if ( showFileSizeBox->isChecked() ==showsize ) return;
	if ( showsize )
	{
		removeLabelFromDataList ( LBL_SIZE );
	}
	else
	{
		appendLabelToDataList ( LBL_SIZE );
	}
}

void rp3dReconCls::showFileLMDSlot()
{
	if ( showLMDBox->isChecked() ==showlastmodify ) return;
	if ( showlastmodify )
	{
		removeLabelFromDataList ( LBL_LASTMODIFY );
	}
	else
	{
		appendLabelToDataList ( LBL_LASTMODIFY );
	}
}

void rp3dReconCls::showFileLMTSlot()
{
	if ( showLMTBox->isChecked() ==showlastmodifyt ) return;
	if ( showlastmodifyt )
	{
		removeLabelFromDataList ( LBL_LASTMODIFYT );
	}
	else
	{
		appendLabelToDataList ( LBL_LASTMODIFYT );
	}
}

void rp3dReconCls::dropEvent ( QDropEvent *e )
{
	if ( dropeventveto ) return;
	dropeventveto=true;
	const char FIELD_SEP = '\n';
	QStringList s = QStringList::split ( FIELD_SEP,e->encodedData ( "text/plain" ) );
	if ( s.count() >0 )
	{
		dinfs.clear();
		for ( QStringList::Iterator it = s.begin(); it != s.end(); ++it )
		{
			if ( ( *it ).startsWith ( "file://" ) )
			{
				dinfs+= ( *it ).remove ( 0,7 );
			}
			else
			{
				dinfs+= ( *it );
			}
		}
		proc_infs ( &dinfs );
	}
	dropeventveto=false;
}

void rp3dReconCls::dragEnterEvent ( QDragEnterEvent *e )
{
	switch ( e->action() )
	{
		case QDropEvent::Copy:
		case QDropEvent::Move:
			e->acceptAction();
			break;
		default:
			return;
	}
}

void rp3dReconCls::cleLogSlot()
{
	msgBox->clear();
}

void rp3dReconCls::wrapLogSlot()
{
	if ( wrapLogBox->isChecked() )
	{
		msgBox->setWordWrap ( QTextEdit::WidgetWidth );
		msgBox->setWrapPolicy ( QTextEdit::Anywhere );
	}
	else
	{
		msgBox->setWordWrap ( QTextEdit::NoWrap );
	}
}

void rp3dReconCls::switchButPal ( QPushButton *b, bool on )
{
	QColor fgcol=paletteForegroundColor();
	QColor bgcol=paletteBackgroundColor();
	QFont tfont=b->font();

	if ( on )
	{
		tfont.setBold ( true );
		b->setPaletteForegroundColor ( "green" );
//		b->setPaletteBackgroundColor ( qRgb ( 152,128,255 ) );
		b->setPaletteBackgroundColor ( qRgb ( 0,122,255 ) );
		b->setFont ( tfont );
	}
	else
	{
		tfont.setBold ( false );
		b->setPaletteForegroundColor ( fgcol );
		b->setPaletteBackgroundColor ( bgcol );
		b->setFont ( tfont );
	}
}

void rp3dReconCls::switchControl ( int idin )
{
	int id=idin;
	if ( id<0 ) id=0;
	if ( id>WID_MAX ) id=WID_MAX;
	switchButPal ( controlButs[currentPage],false );
	if ( controlButs[id]->isOn() )
	{
		controlStack->raiseWidget ( id );
		controlButs[currentPage]->setOn ( false );
		currentPage=id;
	}
	else
	{
		if ( currentPage==id )
		{
			currentPage=id+1;
			if ( currentPage>WID_MAX ) currentPage=0;
			controlStack->raiseWidget ( currentPage );
			controlButs[currentPage]->setOn ( true );
		}
		else
		{
		}
	}
	switchButPal ( controlButs[currentPage],true );
}
void rp3dReconCls::operationSlot()
{
	switchControl ( WID_OPERATION );
	saveConfig ( HOME+CONFIG );
}
void rp3dReconCls::settingsSlot()
{
	switchControl ( WID_SETTINGS );
}
void rp3dReconCls::findSlot()
{
	switchControl ( WID_FIND );
}
void rp3dReconCls::runSlot()
{
	switchControl ( WID_RUN );
}
void rp3dReconCls::etcSlot()
{
	switchControl ( WID_ETC );
}
void rp3dReconCls::logSlot()
{
	if ( logBut->isOn() )
	{
		msgBox->show();
	}
	else
	{
		msgBox->hide();
	}
	msgBox->setEnabled ( logBut->isOn() );
}

void rp3dReconCls::lockSlot()
{
	WFlags wf=Qt::WStyle_Customize|Qt::WType_TopLevel|Qt::WStyle_DialogBorder;
	QColor bg=paletteBackgroundColor();
	stayTopBox->setChecked ( lockBut->isOn() );
	if ( lockBut->isOn() )
	{
		wf |= Qt::WStyle_StaysOnTop;
		bg.setRgb ( 0,255,255 );

	}
	else
	{
	}
	lockBut->setPaletteBackgroundColor ( bg );
	reparent ( NULL,wf,pos(),true );
//  	setWFlags(wf);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}

void rp3dReconCls::stayTopSlot()
{
	lockBut->setOn ( stayTopBox->isChecked() );
	lockSlot();
}

void rp3dReconCls::canCommitSlot()
{
// 	if ( ! commitInfoBut->isEnabled() )  commitInfoBut->setEnabled ( true );
	if ( ! clearInfoBut->isEnabled() )   clearInfoBut->setEnabled ( true );
	if ( autoSetFilenameBox->isChecked() ) setOutputFilenameSlot ( false );
}

void rp3dReconCls::setOutputFilenameSlot()
{
	setOutputFilenameSlot ( true );
}
void rp3dReconCls::setOutputFilenameSlot ( bool setpath )
{
	QString dir,file;
	QString fullpath;

	if ( studyIdBox->text().isEmpty()
	        ||subjectIdBox->text().isEmpty()
	        ||bodyPartBox->currentText().isEmpty() )
	{
		file="";
	}
	else
	{

		file=studyDateBox->date().toString ( "yyyyMMdd" )
		     +"_"
		     +studyIdBox->text()
		     +"_"
		     +subjectIdBox->text()
		     +"_"
		     +bodyPartBox->currentText();
	}

	if ( setpath )
	{
		dir=outputPath();
		if ( !dir.isEmpty() ) dir=dir+"/";//<<<<<<<<<<<<<<<<<<
		fullpath=dir+file;
	}
	else
	{
		int p=foutBox->text().findRev ( '/' );
		if ( p>=0 )
		{
			fullpath=foutBox->text().replace ( p+1, ( foutBox->text().length()- ( p+1 ) ),file );
		}
		else
		{
			fullpath=file;
		}
	}

	foutBox->setText ( fullpath );
	lastimagefile=file;
	lastimagefilefull=fullpath;
}

void rp3dReconCls::commitInfoSlot()
{
	double u=DUFACTOR[doseUnitBox->currentItem() ];

	setenv ( "RP3STUDYDESC",studyDescEdit->text(),1 );
	setenv ( "RP3DERIVDESC",derivDescEdit->text(),1 );

	setenv ( "RP3PID",subjectIdBox->text(),1 );
	setenv ( "RP3PNAME",subjectNameBox->text(),1 );
	setenv ( "RP3PDOB",dobBox->date().toString ( "yyyyMMdd" ),1 );
	setenv ( "RP3PSEX",sexBox->currentText(),1 );

	setenv ( "RP3PWEIGHT",QString::number ( weightBox->value() ),1 );
	setenv ( "RP3PHEIGHT",QString::number ( heightBox->value() ),1 );

	setenv ( "RP3SID",studyIdBox->text(),1 );
	setenv ( "RP3SYEAR",studyDateBox->date().toString ( "yyyy" ),1 );
	setenv ( "RP3SMONTH",studyDateBox->date().toString ( "MM" ),1 );
	setenv ( "RP3SDAY",studyDateBox->date().toString ( "dd" ),1 );
	setenv ( "RP3SHOUR",startTimeBox->time().toString ( "hh" ),1 );
	setenv ( "RP3SMINUTE",startTimeBox->time().toString ( "mm" ),1 );
	setenv ( "RP3SSECOND","00",1 );
	setenv ( "RP3CF",QString::number ( CFBox->value() ),1 );

	setenv ( "RP3SPART",bodyPartBox->currentText(),1 );
	setenv ( "RP3SINT",injectionTimeBox->time().toString ( "hh:mm" ),1 );
	setenv ( "RP3SDOSE",QString::number ( totalDoseBox->value() *u ),1 );
	setenv ( "RP3RADIOPHAR", rpBox->currentText(),1 );
	setenv ( "RP3HALFLIFE", halflifeBox->currentText(),1 );
	setenv ( "RP3SSCAND",QString::number ( scanDurationBox->value() *60 ),1 );

	setenv ( "RP3INSTITUTION",institutionBox->text(),1 );
	setenv ( "RP3OPERATOR",operatorBox->currentText(),1 );
	if ( !operatorBox->currentText().isEmpty() ) operatorBox->addToHistory ( operatorBox->currentText() );

	if ( !rpBox->currentText().isEmpty() ) rpBox->addToHistory ( rpBox->currentText() );

	if ( !halflifeBox->currentText().isEmpty() ) halflifeBox->addToHistory ( halflifeBox->currentText() );

	if ( !bodyPartBox->currentText().isEmpty() ) bodyPartBox->addToHistory ( bodyPartBox->currentText() );

	setenv ( "RP3IMGORIPAT",iopCode,1 );

	saveConfig ( HOME+CONFIG );
}

void rp3dReconCls::setAgeSlot()
{
	QDate now = studyDateBox->date();
	int y;
	y=now.year()-dobBox->date().year();
	QDate tmp = QDate ( now.year(),dobBox->date().month(),dobBox->date().day() );
	if ( tmp>now ) y--;
	setenv ( "RP3PAGE",QString::number ( y ),1 );
	ageBox->setText ( QString::number ( y ) );
}

void rp3dReconCls::clearInfoSlot()
{
	clearInfoSlot ( true );
}
void rp3dReconCls::clearInfoSlot ( bool all )
{
	if ( confirmCleInfoBox->isChecked() )
	{
		if ( KMessageBox::Yes!=KMessageBox::warningYesNo (
		            this,
		            tr ( "Clear Study/Subject Information?" ),
		            tr ( "Warning" ) ) ) return;
	}

	QTime t=QDateTime::currentDateTime().time();
	QDate d=QDateTime::currentDateTime().date();

	studyIdBox->clear();
	studyDateBox->setDate ( d );
	scanDurationBox->setValue ( 0 );
	startTimeBox->setTime ( t );
	injectionTimeBox->setTime ( t );
	bodyPartBox->setCurrentText ( "" );

	totalDoseBox->setValue ( 0 );
	subjectIdBox->clear();
	subjectNameBox->clear();
	dobBox->setDate ( d );
	heightBox->setValue ( 0 );
	weightBox->setValue ( 0 );
	sexBox->setCurrentItem ( 2 );

	derivDescEdit->clear();
	studyDescEdit->clear();
	ageBox->clear();

	if ( all )
	{
		operatorBox->clear();
		institutionBox->clear();
		CFBox->setValue ( 1 );
		doseUnitBox->setCurrentItem ( 0 );
		rpBox->clear();
		halflifeBox->clear();
		setenv ( "RP3INSTITUTION","",1 );
		setenv ( "RP3OPERATOR","",1 );
		setenv ( "RP3CF","",1 );
		setenv ( "RP3RADIOPHAR","",1 );
		setenv ( "RP3HALFLIFE","",1 );
	}

	setenv ( "RP3PID","",1 );
	setenv ( "RP3PNAME","",1 );
	setenv ( "RP3PDOB","",1 );
	setenv ( "RP3PSEX","",1 );
	setenv ( "RP3PAGE","",1 );
	setenv ( "RP3PWEIGHT","",1 );
	setenv ( "RP3PHEIGHT","",1 );

	setenv ( "RP3SID","",1 );
	setenv ( "RP3SYEAR","",1 );
	setenv ( "RP3SMONTH","",1 );
	setenv ( "RP3SMONTH","",1 );
	setenv ( "RP3SDAY","",1 );
	setenv ( "RP3SHOUR","",1 );
	setenv ( "RP3SMINUTE","",1 );
	setenv ( "RP3SSECOND","",1 );

	setenv ( "RP3SPART","",1 );
	setenv ( "RP3SINT","",1 );
	setenv ( "RP3SDOSE","",1 );
	setenv ( "RP3SSCAND","",1 );

	setenv ( "RP3STUDYDESC","",1 );
	setenv ( "RP3DERIVDESC","",1 );

	setenv ( "RP3IMGORIPAT","",1 );
}

void rp3dReconCls::doseUnitSlot()
{
	int i=doseUnitBox->currentItem();
	double f=DUFACTOR[currentDoseUnit]/DUFACTOR[i];
	totalDoseBox->setValue ( totalDoseBox->value() *f );
	currentDoseUnit=i;
}

void rp3dReconCls::openNormFile ( QString mess, QString f, QLineEdit *e )
{
	e->setText ( KFileDialog::getOpenFileName ( "",
	             f+"\n*.*|All (*.*)",
	             this,
	             mess ) );

}
void rp3dReconCls::openSenFileSlot()
{
	openNormFile ( "Select sensitivity correction file",
	               "*.img|Sensitivity image(*.img)",
	               senFileEdit );
}
void rp3dReconCls::openUniFileSlot()
{
	openNormFile ( "Select uniformity correction file",
	               "*.tmo|Histogram (*.tmo)",
	               uniFileEdit );
}

void rp3dReconCls::rdManSlot()
{
	rdmancls *sw = new rdmancls();
	sw->datapath=datapathEdit;
	sw->exec();
	delete sw;
}

QString rp3dReconCls::outputPath()
{
	if ( outputDefBox->isChecked() )
	{
		if ( !datapathEdit->text().isEmpty() ) return datapathEdit->text();
	}
	else if ( rememberFileLocBox->isChecked() )
	{
		if ( !lastodir.isEmpty() ) return lastodir;
	}
	else
	{
		if ( !lastdir.isEmpty() ) return lastdir;
	}
	return "";
}

void rp3dReconCls::outfSelected()
{
	QString f=outfListBox->currentText().remove ( 0,labelwidth );
	if ( getFileType ( f ) ==FT_DICM )
	{
		if ( f==lastoutimagefile )
		{
			viewBut->setEnabled ( true );
		}
		else
		{
			viewBut->setEnabled ( false );
		}
		foutBox->setText ( f );
	}
	else
	{
		fhoutBox->setText ( f );
	}
}

int rp3dReconCls::adjCol ( bool *d, int c, int *off )
{
	int const col_min = 200;
	int col_deg;
	int cc=c;

	if ( c>231 )
	{
		col_deg=1;
	}
	else if ( c>214 )
	{
		col_deg=4;
	}
	else
	{
		col_deg=9;
	}

	if ( *off<0 )
	{
		( *off ) ++;
		return cc;
	}
	if ( *d )
	{
		cc+=col_deg;
		if ( cc>255 )
		{
			*d=false;
			cc=255;
		}
	}
	else
	{
		cc-=col_deg;
		if ( cc<col_min )
		{
			*d=true;
			cc=col_min;
		}
	}
	return cc;
}

void rp3dReconCls::resetTimerEvent ( int id )
{
	QWidget *w;
	switch ( id )
	{
		case 0:
			w=studyIdBox;
			break;
		case 1:
			w=bodyPartBox->lineEdit();
			break;
		case 2:
			w=subjectIdBox;
			break;
	}

	w->setPaletteBackgroundColor ( "white" );
	theOks[id]=true;
}
void rp3dReconCls::doTimerEvent ( int id )
{
	QWidget *w;
	int c1;
	switch ( id )
	{
		case 0:
			w=studyIdBox;
			break;
		case 1:
			w=bodyPartBox->lineEdit();
			break;
		case 2:
			w=subjectIdBox;
			break;
	}
	theOks[id]=false;
	c1=adjCol ( &theFlips[id],w->paletteBackgroundColor().green(), &theOffs[id] );
	w->setPaletteBackgroundColor ( qRgb ( 255,c1,255 ) );
}

void rp3dReconCls::timerEvent ( QTimerEvent *e )
{
	if ( timerVeto ) return;
	timerVeto=true;
	if ( studyIdBox->text().isEmpty() )
	{
		doTimerEvent ( 0 );
	}
	else if ( !theOks[0] )
	{
		resetTimerEvent ( 0 );
	}
	if ( bodyPartBox->currentText().isEmpty() )
	{
		doTimerEvent ( 1 );
	}
	else if ( !theOks[1] )
	{
		resetTimerEvent ( 1 );
	}
	if ( subjectIdBox->text().isEmpty() )
	{
		doTimerEvent ( 2 );
	}
	else if ( !theOks[2] )
	{
		resetTimerEvent ( 2 );
	}
	timerVeto=false;
}

void rp3dReconCls::bodyPartEnterSlot()
{
	if ( bodyPartBox->currentText().isEmpty() ) return;
	bodyPartBox->addToHistory ( bodyPartBox->currentText() );
}

void rp3dReconCls::showHelp()
{
	QString manstr=
	    tr (
	        "Ctrl+A\tSelect all\n"
	        "Ctrl+O\tOpen files\n"
	        "Ctrl+R\tReverse selection\n"
	        "Ctrl+C\tClear selection\n"
	        "Ctrl+X\tRemove seleced\n"
	        "Ctrl+L\tClear entry\n"
	        "\n"
	        "A\tOpen files\n"
	        "O\tOperation\n"
	        "S\tSettings\n"
	        "F\tFind files\n"
	        "R\tRun shell commands\n"
	        "E\tetc\n"
	        "L\tShow/hide Log window"
	    );
	QMessageBox mb ( "Usage",
	                 manstr,
	                 QMessageBox::NoIcon,
	                 QMessageBox::Ok | QMessageBox::Default,
	                 QMessageBox::NoButton,
	                 QMessageBox::NoButton ,
	                 0,
	                 "man",
	                 false );
	mb.exec();
}

void rp3dReconCls::cleHisSlot()
{
	int clearSettingsFlag=0;
	cleardlgcls *w = new cleardlgcls ( this );
	w->op=operatorBox;
	w->bp=bodyPartBox;
	w->rp=rpBox;
	w->hl=halflifeBox;
	w->re=emilyOptBox;
	w->sh=runComBox;
	w->flag=&clearSettingsFlag;
	w->exec();
	delete w;
	if ( clearSettingsFlag==0 ) return;
	QFile conf ( HOME+CONFIG );
	conf.remove();
	saveConfig ( HOME+CONFIG,clearSettingsFlag );
	loadConfig ( HOME+CONFIG );
}

void rp3dReconCls::saveReconSetting ( QString n )
{
	KConfig *conf = new KConfig ( HOME+CONFIG );
	if ( conf==NULL )
	{
		setmanw->mess="Failed to open config!";
		setmanw->rc=-1;
	}
	else
	{
		saveReconConfig ( conf,n );
		setmanw->rc=0;
		setmanw->mess="Settings `"+n+"' saved.";
		setmanw->saved();
		delete conf;
	}
	setmanw->showMess();
}
void rp3dReconCls::loadReconSetting ( QString n )
{
	KConfig *conf=new KConfig ( HOME+CONFIG );
	if ( conf==NULL )
	{
		setmanw->mess="Failed to open config!";
		setmanw->rc=-1;
	}
	else
	{
		if ( conf->hasGroup ( n ) )
		{
			loadReconConfig ( conf,n );
			setmanw->rc=0;
			setmanw->mess="Settings `"+n+"' loaded.";
		}
		else
		{
			setmanw->rc=1;
			setmanw->mess="No such settings `"+n+"' found!";
		}
		delete conf;
	}
	setmanw->showMess();
}

void rp3dReconCls::deleReconSetting ( QString n )
{
	KConfig *conf=new KConfig ( HOME+CONFIG );
	if ( conf==NULL )
	{
		setmanw->rc=-1;
		setmanw->mess="Failed to open config!";
	}
	else
	{
		if ( conf->hasGroup ( n ) )
		{
			conf->deleteGroup ( n );
			setmanw->rc=0;
			setmanw->mess="Settings `"+n+"' has been removed";
		}
		else
		{
			setmanw->rc=1;
			setmanw->mess="No such settings `"+n+"' found!";
		}
		delete conf;
	}
	setmanw->showMess();
}

void rp3dReconCls::setManSlot()
{
	if ( setmanw!=NULL ) delete ( setmanw );
	setmanw = new setManCls ( this );
	connect ( setmanw, SIGNAL ( saveSetting ( QString ) ),this,SLOT ( saveReconSetting ( QString ) ) );
	connect ( setmanw, SIGNAL ( loadSetting ( QString ) ),this,SLOT ( loadReconSetting ( QString ) ) );
	connect ( setmanw, SIGNAL ( deleSetting ( QString ) ),this,SLOT ( deleReconSetting ( QString ) ) );

	KConfig *conf;

	conf= new KConfig ( HOME+CONFIG );
	if ( conf!=NULL )
	{
		KConfigGroup histGroup ( conf,"History" );
		setmanw->setNameHistComp ( histGroup.readListEntry ( "reconstruction settings name history" ),histGroup.readListEntry ( "reconstruction settings name completion" ) );
		delete conf;
	}

	setmanw->exec();

	conf = new KConfig ( HOME+CONFIG );
	if ( conf!=NULL )
	{
		KConfigGroup histGroup ( conf,"History" );
		QStringList h,c;
		setmanw->getNameHistComp ( &h,&c );
		histGroup.writeEntry ( "reconstruction settings name history",h );
		histGroup.writeEntry ( "reconstruction settings name completion",c );
		histGroup.sync();
		delete conf;
	}

	delete setmanw;
	setmanw=NULL;
}

void rp3dReconCls::oriSlot()
{
	oriCls *w=new oriCls ( this );
	w->exec();
	iopCode=w->getImageOrientPat();
	delete w;
}